本文主要介绍Mybatis中强大的resultMap函数的相关信息。通过示例代码进行了非常详细的介绍,对大家学习或使用Mybatis有一定的参考价值。有需要的话一起学吧。
前言
在Mybatis中,有一个强大的功能元素resultMap。当我们想要将JDBC结果集中的数据转换成合理的Java对象时,您可以感受到它非凡的特性。正如其官员所说:
resultMap元素是MyBatis中最重要和最强大的元素。它可以把你从90%的JDBC结果集数据提取代码中解放出来,在某些情况下,允许你做一些JDBC不支持的操作。事实上,在为一些复杂的语句(如连接)编写映射代码时,一个resultMap可以用相同的函数替换数千行代码。ResultMap的设计思想是,对于简单的语句,不需要配置显式的结果映射,对于更复杂的语句,只需要描述它们之间的关系。
一、字段映射
在Mybatis中,映射结果的最简单方法是通过typeAliases来处理它。
如果要这样做,那么第一步是配置实体类包的路径:
my batis . type-aliases-package=com . XXX . entity
该路径下的所有类都将在TYPE_ALIASES容器中注册。当我们指定返回值类型时,我们可以只使用别名。
例如,我们有一个用户类:
@数据
公共类用户{
私有字符串id;
私有字符串用户名;
私有字符串密码;
私有字符串地址;
私人字符串电子邮件;
}
如果数据库中表的字段与用户类的属性名一致,我们可以使用resultType将其返回。
select id= get users result type= User
挑选
u.id,
用户名,
密码,
u .地址,
电子邮件
从
用户u
/选择
当然,这是属性和字段名完全相同的理想情况。但实际上有一些不一致的地方。这时候我们的resultMap就要出现了。
如果用户类保持不变,但SQL语句发生了变化,则id将更改为uid。
select id= get users result type= User
挑选
u.id作为uid,
用户名,
密码,
u .地址,
电子邮件
从
用户u
/选择
然后,在结果集中,我们将丢失id数据。这时,我们可以定义一个resultMap来映射不同的字段。
结果映射id=getUserByIdMap type=User
结果属性=id 列=uid/result
/结果映射
然后,我们将上面select语句中的resultType修改为resultMap=getUserByIdMap 。
这里的列对应于数据库的列名或别名;属性对应于结果集的字段或属性。
这是resultMap最简单也是最基本的用法:字段映射。
下面,我们来看看其他几个标签是如何应用的。
元素名称
形容
构造器
当用于实例化一个类时,结果被注入构造方法。
联合
关联一个对象。
收藏品
关联多个对象
二、构造方法
如果要将结果注入到构造函数中,可以使用constructor元素。
例如,我们的用户类添加了一个构造方法:
公共用户(字符串id,字符串名称){
this . id=id -;
this . username=name -;
}
我们需要在resultMap中定义构造函数元素:
结果映射id=getUserByIdMap type=User
构造器
idArg column= id name= id Java type= string /idArg
arg column= username name= name Java type= string /arg
/构造函数
/结果映射
列表示数据库字段名或别名;Name是构造函数中的参数名;JavaType指定参数的类型。
可以想象,以这种方式指定构造方法后,我们的结果集中的id和username属性会发生变化。
{
id: 1001 -,
用户名:后羿-,
密码: 123456 ,
地址,北京市海淀区,
电子邮件: 510273027@qq.com
}
三、关联
在实际业务中,我们的用户一般都有一个角色。那么用户类一般用实体类来表示。
@数据
公共类用户{
//省略用户属性.
//角色信息
私人角色角色;
}
当我们查询用户时,如果我们还想查看其角色信息,我们将编写这样的查询语句:
select id= getuser byid result type= User
挑选
u.id,
用户名,
密码,
u .地址,
电子邮件,
r.id为 role_id ,
r.name为“角色名称”
从
用户u
在u.id=ur.user_id上左连接user_roles ur
r.id=ur.role_id上的左联接角色r
其中u.id=#{id}
/选择
如上所述,需要查询单个用户及其角色信息。但是,在这里,我们不能使用resultType=User返回。
毕竟User类中只有一个Role对象,没有role_id和role_name字段属性。
所以,我们要用联想来联系它们。
结果映射id=用户映射类型=用户
id属性=id 列=id/id
结果属性=用户名列=用户名/结果
结果属性=密码列=密码/结果
结果属性=地址列=地址/结果
结果属性=电子邮件列=电子邮件/结果
关联属性=role javaType=Role
id属性=id 列=role_id/id
结果属性=名称列=角色名称/结果
/关联
/结果映射
最后,我们可以一起显示角色信息:
{
id: 1001 ,
用户名:后羿,
密码: 123456 ,
地址,北京市海淀区,
邮箱: 510273027@qq.com ,
角色:{
id: 3 ,
姓名:射手
}
}
事实上,如果你确定关联信息是一对一的,有一个更简单的方法来替换关联。我们将在本文的第五部分看到它是如何实现的——自动填充关联对象。
四、集合
1、集合的嵌套结果映射
上图,我们看到一个用户后羿,他的角色是射手;但是很多时候,我们每个人都不可能只有一个角色。因此,我们需要将User类中的role属性的类型改为List。
@数据
公共类用户{
//省略用户属性.
//角色信息
私有列表角色角色;
}
现在变成了多个角色对应的用户,所以不是简单的关联。
因为关联处理与一种类型的关联;这里我们有多种类型的关联,所以我们需要使用集合属性。
我们的总体结果图将如下所示:
结果映射id=用户映射类型=用户
id属性=id 列=id/id
结果属性=用户名列=用户名/结果
结果属性=密码列=密码/结果
结果属性=地址列=地址/结果
结果属性=电子邮件列=电子邮件/结果
类型为“Role”的集合属性为“roles”
id属性=id 列=role_id/id
结果属性=名称列=角色名称/结果
/收藏
/结果映射
这样,即使你有多个字符,你也能正确显示:
{
id: 1003 ,
用户名:丢西姆的故事,
密码: 123456 ,
地址,北京市东城区,
邮箱: 510273027@qq.com ,
角色:[
{
id: 1 ,
姓名:钟丹
},
{
id: 2 ,
姓名:打野
}
]
}
2、集合的嵌套 Select 查询
在大多数业务系统中,我们都会有一个菜单表,如下,一个菜单表:
身份证明(identification)
名字
全球资源定位器(Uniform Resource Locator)
家长id
一个
系统管理
0
1001
用户管理
/用户
一个
1002
角色管理
/角色
一个
1003
单位管理
/雇主
一个
2
平台监控
0
2001
系统监控
/系统/监视器
2
2002
数据监控
/数据/监视器
2
这里我们将菜单分为两级。当我们把菜单返回到前端的时候,也是需要分级的,不可能横向显示这七条数据。所以,这里我们的菜单实体类如下:
@数据
公共课程菜单{
私有字符串id;
私有字符串名称;
私有字符串url
私有字符串parent _ id
private ListMenu childMenu
}
一级菜单,包含一个二级菜单列表,这里用childMenu表示。
在SQL语句中,如果没有parent_id字段属性,我们将首先检查所有一级菜单:
select id= get menus result map= menus map
挑选
医学博士,
m.name,
m.url,
m.parent_id
从
菜单m
其中1=1
选择
当test=parent_id!=null
并且m.parent_id=#{parent_id}
/什么时候
否则
并且m.parent_id=0
/否则
/选择
/选择
这个查询语句,不传递任何参数,我们会得到两个一级菜单的数据。
那么,当这个方法只调用一次的时候,如何才能把所有的菜单信息都找出来并分层显示呢?
让我们看看menusMap的定义:
结果映射id=menusMap type=Menu
id属性=id 列=id/id
结果属性=名称列=名称/结果
结果属性=url 列=url/result
结果属性= desc 列= desc /结果
结果属性=parent_id 列= parent _ id /结果
type= Menu select= get menus column= { parent _ id=id } /collection的集合属性=childMenu
/结果映射
关注收集元素:
property=“child menu”对应于菜单中的子菜单列表;
of type=“Menu”对应于返回数据的类型;
Select=getMenus 指定Select语句的id;
column=“{ parent _ id=id }”是参数的表达式。
这个系列的全部意义可以理解如下:
通过getMenus的SELECT语句获取一级菜单中childMenu属性的结果;在上面的SELECT语句中,需要传递一个parent_id参数;该参数的值是一级菜单中的id。
这样我们就可以得到所有的分级菜单信息。
[
{
id: 1 ,
名称:系统管理,
parent_id: 0 ,
子菜单:[
{
id: 1001 ,
名称:用户管理,
URL“:/用户”,
parent_id: 1
},
{
id: 1002 ,
名称:角色管理,
URL“:/角色”,
parent_id: 1
},
{
id: 1003 ,
姓名:公司管理层,
URL :/雇主,
parent_id: 1
}
]
},
{
id: 2 ,
名称:平台监控,
parent_id: 0 ,
子菜单:[
{
id: 2001 ,
名称:系统监控,
URL :/系统/监视器,
parent_id: 2
},
{
id: 2002 ,
名称:数据监控,
URL :/数据/监视器,
parent_id: 2
}
]
}
]
五、自动填充关联对象
我们知道当Mybatis解析返回值时。
第一步是获取返回值类型,获取类对象,然后获取构造函数,设置可访问和返回的实例,然后包装成元对象对象。
从数据库rs得到结果后,会调用metaobject.setvalue(字符串名,对象值)来填充对象。
有趣的是,在这个过程中,它会用.
如果名称属性包含。符号之前找到属性名。符号,并将其视为实体对象。
可能作者这里描述的不够直观,我们来看例子。
在本文的第三部分,我们有一个用户对应一个角色的例子。
其中,用户类定义如下:
@数据
公共类用户{
//省略用户属性.
//角色信息
私人角色角色;
}
这里不需要定义resultMap,只需要返回resultType=User。但是,角色信息的别名需要修改,重点是。符号。
select id= get userlist result type= User
挑选
u.id,
用户名,
密码,
u .地址,
电子邮件,
r.id为 role.id ,
r.name为“role.name”
从
用户u
在u.id=ur.user_id上左连接user_roles ur
r.id=ur.role_id上的左联接角色r
/选择
这样,当Mybatis解析到Role.id属性时,发现角色别名被。符号,角色对象将首先被初始化,值将被赋予id属性。
相关代码如图所示:
总结
这就是本文的全部内容。希望这篇文章的内容对你的学习或工作有一定的参考价值。谢谢你的支持。