mybatis一对一查询功能
作者:精品唯居
所谓的一对一查询,就是说我们在查询一个表的数据的时候,需要关联查询其他表的数据。
需求
首先说一个使用一对一查询的小需求吧:假设我们在查询某一个订单的信息的时候,需要关联查询出创建这个订单对应的用户信息。表模型如下(
ResultType
sql语句的书写
首先,我们要对我们的需求进行分析。1.我们需要确定这个需求需要涉及到哪两张表,其中哪个是主表,哪个是关联表。具体怎么确定,还是看需求——我们的需求是说,在查询订单的时候,顺带着查出创建这个订单的用户。那么,已经很显然了。我们的主表是订单表(orders)。而我们的关联表则是用户表(user)。
这个时候,我们就可以写出来如下sql语句了:
select * from orders
这个时候,我们就应该考虑这个问题了:我们在关联查询的时候应该使用内链接?还是外链接?对于搞不清内链接外链接的区别的同学,我这里先简单的介绍一下,等以后有时间了,再详细写一篇博客说明:内连接是只显示满足条件的。外链接分为左外和右外链接:左连接显示左边全部的再加上右边与左边相同的;右连接显示右边全部的和左边与右边相同的。
我们的需求是通过订单去关联用户,而由于在orders表中有一个外键(userId)。通过外键的去查关联表user表的数据时,userId是user表的主键。这时,只能查到一条user的信息,而这条记录不会导致我们的主查询结果发生改变。所以,我们选择内链接查询。这时候,我们的sql语句是这样的:
select * from orders,user where orders.user_id = user.id
查询完成后,出现结果如下:
这时,问题来了,我们发现,这个时候出现了两个id,这就会导致我们的数据在输出的时候封装到对象时会出现问题。而且,User_id 这一列和我们的用户id数据是重复的。我们需要改造我们的sql。怎么改造呢?
因为我们的主表数据是要全部查询的,而用户表我们只需要username,sex,adress这三个信息(这里是假设,没必要纠结需要的是啥信息)。那么我们就需要手动指定我们的sql语句的查询字段了:
SELECT orders.*, USER.username, USER.sex, USER.address FROM orders, USER WHERE orders.user_id = user.id
前面的这些都是在我们的sql链接工具上进行查询的,当可以显示我们需要的数据库后,我们的sql语句就确定了。这时我们该开始下一步了:
创建pojo
我们需要将查询到的结果,通过mybatis框架将数据封装到对应的对象。那么,问题来了,这个查询到的数据由谁来接收?我们如果要将上边sql查询的结果映射到pojo中,pojo中必须包括所有查询列名。但是不管是原来的Orders类还是User类,都没有办法映射全部的字段。这时,我们有一个很简单的解决办法:根据返回的字段,专门写一个类,让它包含所有的查询结果,然后让这个类去接收这个返回的结果集。
这时有个小技巧,我们的新的pojo中,不需要将所有的字段全部都写上,我们可以让新pojo去继承我们的包含结果集中查询字段较多的一个类,然后将其他需要的数据写到这个子类中即可。
创建pojo完成后,我们就需要根据规范去创建我们的映射文件和写对应的接口中的方法:
mapper.xml
mapper.java中的接口:
ResultMap
sql语句上,resultType 和resuleMap实现的方式一样,这里就直接跳过了。
使用resultMap映射的思路
我们知道,使用pojo的时候,我们可以将一些数据封装到pojo的对象属性中,他的属性可以是简单类型,也可以是另外一个pojo。这时,我们可以这么做:
使用resultMap将查询结果中的订单信息映射到Orders对象中,在orders类中添加User属性,将关联查询出来的用户信息映射到orders对象中的user属性中。
Orders类中添加user属性
mapper.xml
用resultMap的方法将结果集进行映射的时候,我们需要进行两个操作,一个是定义resultMap,设置每个查到的结果集中的列相对应的对象的属性。这个比较麻烦但是不难。二就是定义我们的statement。
resultMap
resultMap实现的基本思路我们刚才已经说了。而且也在orders的pojo类中增加了相应的属性了。接下啦,就是写一个resultMap,将整个查询的结果映射到Orders中在这里面,首先是order订单的映射。就是直接用id 和result标签将两者相互对应即可。然后就是,关联的用户信息的映射,这时候需要用到一个association的标签,将在orders类中的user字段与User类进行映射,然后在其内部还是用id和result标签,将查询的数据和User的属性相映射。
具体代码如下:
<!-- 订单查询关联用户的resultMap 将整个查询的结果映射到cn.mybatis.po.Orders中 --> <resultMap type="cn.mybatis.po.Orders" id="OrdersUserResultMap"> <!-- 配置映射的订单信息 --> <!-- id:指定查询列中的唯 一标识,订单信息的中的唯 一标识,如果有多个列组成唯一标识,配置多个id column:订单信息的唯 一标识 列 property:订单信息的唯 一标识 列所映射到Orders中哪个属性 --> <id column="id" property="id"/> <result column="user_id" property="userId"/> <result column="number" property="number"/> <result column="createtime" property="createtime"/> <result column="note" property=note/> <!-- 配置映射的关联的用户信息 --> <!-- association:用于映射关联查询单个对象的信息 property:要将关联查询的用户信息映射到Orders中哪个属性 --> <association property="user" javaType="cn.mybatis.po.User"> <!-- id:关联查询用户的唯 一标识 column:指定唯 一标识用户信息的列 javaType:映射到user的哪个属性 --> <id column="user_id" property="id"/> <result column="username" property="username"/> <result column="sex" property="sex"/> <result column="address" property="address"/> </association> </resultMap>
statement
statement比较简单,就是将返回结果集的映射方式改成resultMap。然后将返回类型只想我们刚完成的resultMap就可以了。
mapper.java
两者的区别
实现一对一查询的方法说完了,接下来分析下它们的不同之处,和优劣之处。
首先,都需要对pojo进行修改,一个是增加一个pojo类另外一个则是修改pojo的字段。个人感觉,根据设计模式中的开闭原则。resultType要比resultMap更好一些。
其次,简易程度上来说,使用resultType实现较为简单。从这点讲,resultType也要比resultMap更好一些。
不过resultMap可以实现延迟加载,resultType无法实现延迟加载。这方面resultType就不如resultMap更好了。
所以:建议大家,如果没有查询结果的特殊要求的话使用resultType。
以上所述是小编给大家介绍的mybatis一对一查询功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!