在现实的项目中进行数据库建模时,我们要遵循数据库设计范式的要求,会对现实中的业务模型进行拆分,封装在不同的数据表中,表与表之间存在着一对多或是多对多的对应关系。进而,我们对数据库的增删改查操作的主体,也就从单表变成了多表。那么Mybatis中是如何实现这种多表关系的映射呢?
查询结果集ResultMap
resultMap元素是MyBatis中最重要最强大的元素。它就是让你远离90%的需要从结果集中取出数据的JDBC代码的那个东西,而且在一些情形下允许你做一些JDBC不支持的事情。事实上,编写相似于对复杂语句联合映射这些等同的代码,也许可以跨过上千行的代码。
有朋友会问,之前的示例中我们没有用到结果集,不是也可以正确地将数据表中的数据映射到Java对象的属性中吗?是的。这正是resultMap元素设计的初衷,就是简单语句不需要明确的结果映射,而很多复杂语句确实需要描述它们的关系。
resultMap元素中,允许有以下直接子元素:
constructor-类在实例化时,用来注入结果到构造方法中(本文中暂不讲解)
id-作用与result相同,同时可以标识出用这个字段值可以区分其他对象实例。可以理解为数据表中的主键,可以定位数据表中唯一一笔记录
result-将数据表中的字段注入到Java对象属性中
association-关联,简单的讲,就是“有一个”关系,如“用户”有一个“帐号”
collection-集合,顾名思议,就是“有很多”关系,如“客户”有很多“订单”
discriminator-使用结果集决定使用哪个个结果映射(暂不涉及)
1、嵌套查询映射
嵌套查询映射:通过执行另外一个SQL映射语句来返回预期的复杂类型。
想查询出订单的时候去给我关联查询出该订单所属于的用户信息。(查询一张表)
users表和orders表两张表如下:
CREATETABLE`users`( `uid`bigint(20)NOTNULLAUTO_INCREMENT, `uname_uu`varchar(255)DEFAULTNULL, `upwd`varchar(255)DEFAULTNULL, `sex`varchar(255)DEFAULTNULL, `birthday`dateDEFAULTNULL, PRIMARYKEY(`uid`) )ENGINE=InnoDBAUTO_INCREMENT=20DEFAULTCHARSET=utf8; CREATETABLE`orders`( `oid`bigint(255)NOTNULLAUTO_INCREMENT, `oprice`doubleDEFAULTNULL, `createtime`datetimeDEFAULTNULL, `flag`varchar(255)DEFAULTNULLCOMMENT'订单的状态', `uid`bigint(20)DEFAULTNULLCOMMENT'外键', PRIMARYKEY(`oid`), KEY`uid`(`uid`), CONSTRAINT`orders_ibfk_1`FOREIGNKEY(`uid`)REFERENCES`users`(`uid`) )ENGINE=InnoDBAUTO_INCREMENT=4DEFAULTCHARSET=utf8; UserMapper配置文件如下: <!--关联查询出一方--> <!--查询订单的时候去关联查询用户--> <!--a.嵌套查询映射只查询一个表--> <selectid="queryOrderWithUser"resultMap="OrderAndUserMap"> select*fromorders </select> <!--定义一个resultMap--> <!--type:pojo类id:resultMap的唯一标志--> <resultMaptype="order"id="OrderAndUserMap"> <!--如果column和pojo属性名(property)一致可以不写--> <idcolumn="oid"property="oid"/> <!--关联查询出一方 column:外键字段 property:关联对象的属性名 javaType:写pojo类的类型 select:写statement对象的id值 --> <associationcolumn="uid"property="user"javaType="user"select="queryUserByUid"> <!--<resultcolumn="uname_uu"property="uname"/>--> </association> </resultMap> <selectid="queryUserByUid"parameterType="long"resultMap="myUserMap1"> select*fromuserswhereuid=#{uid} </select> <!--配置resultMap--> <!--需要配置需要的所有属性不管列明和属性名是否一致--> <resultMaptype="order"id="OrderAndUserMap2"> <idcolumn="oid"property="oid"/> <resultcolumn="oprice"property="oprice"/> <resultcolumn="flag"property="flag"/> <resultcolumn="createtime"property="createtime"/> <!-- property:属性名 javaType:pojo的类型也可以通过resulteMap指定返回的结果集 --> <associationproperty="user"resultMap="myUserMap1"/> </resultMap> UserMapper.java接口方法如下: //查询订单去关联查询用户 List<Order>queryOrderWithUser(); 测试代码: ////14.查询订单去关联查询用户嵌套查询映射 @Test publicvoidrun14()throwsIOException{ UserMappermapper=sqlSession.getMapper(UserMapper.class); List<Order>c=mapper.queryOrderWithUser(); System.out.println(c); }
2、嵌套结映射
嵌套结果:使用嵌套结果映射来处理重复的联合结果的子集。
UserMapper.xml <selectid="queryUserWithOrder2"resultMap="OrderAndUserMap2"> <!--sql左外连接查询--> select*fromordersasoleftouterjoinusersasuono.uid=u.uid; </select> <!--配置resultMap--> <!--需要配置需要的所有属性不管列明和属性名是否一致--> <resultMaptype="order"id="OrderAndUserMap2"> <idcolumn="oid"property="oid"/> <resultcolumn="oprice"property="oprice"/> <resultcolumn="flag"property="flag"/> <resultcolumn="createtime"property="createtime"/> <!-- property:属性名 javaType:pojo的类型也可以通过resulteMap指定返回的结果集 --> <associationproperty="user"resultMap="myUserMap1"/> </resultMap> <resultMaptype="user"id="myUserMap1"> <!--配置主键映射 column:表的字段 property:pojo的属性 --> <idcolumn="uid"property="uid"/> <!--配置普通属性--> <resultcolumn="uname_uu"property="uname"/> <resultcolumn="sex"property="sex"/> <resultcolumn="birthday"property="birthday"/> </resultMap> UserMapper.java接口方法如下: //查询订单去关联查询用户 List<Order>queryOrderWithUser2(); 测试代码: ////14.查询订单去关联查询用户嵌套查询映射 @Test publicvoidrun14()throwsIOException{ UserMappermapper=sqlSession.getMapper(UserMapper.class); List<Order>c=mapper.queryOrderWithUser2(); System.out.println(c); }
3、查询2个表
自己整一个pojo类把需要用到的user表的字段和order表的字段全都写进去直接用resultType
<selectid="queryUserWithOrder2"resultType="UserOrder"> <!--sql左外连接查询--> select*fromordersasoleftouterjoinusersasuono.uid=u.uid; </select>
最后想要了解更多Java信息的同学可以前往扣丁学堂官网咨询,扣丁学堂Java培训深受学员的喜爱。扣丁学堂不仅有专业的老师和与时俱进的课程体系,还有大量的Java视频教程供学员观看学习哦。扣丁学堂java技术交流群:487098661。