本文主要介绍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属性。
相关代码如图所示:
总结
这就是本文的全部内容。希望这篇文章的内容对你的学习或工作有一定的参考价值。谢谢你的支持。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。