一、前言
前面的时候,小编向大家介绍了Mybatis的使用,总得来说,Mybatis注重的是写sql语句。针对单表 的增删改查还是比较好写的,直接写出SQL语句可以了,但是如果遇到了多表的关联查询,可能就会复杂了点。下面小编就向大家介绍如何进行多表的复杂查询 。
二、关联关系为:一对一查询
方法一:使用resultType
思路:创建一个大实体Model,这个Model是和关联查询的fileld相同,然后在mapper中写sql,resultType写返回Model。
需求:一个订单对应一个用户,查询订单的时候顺便把用户信息查出来
从新建立一个Model,这个model继承Orders类,并添加本次查询的User的属性:
思路:创建一个大实体Model,这个Model是和关联查询的fileld相同,然后在mapper中写sql,resultType写返回Model。
需求:一个订单对应一个用户,查询订单的时候顺便把用户信息查出来
从新建立一个Model,这个model继承Orders类,并添加本次查询的User的属性:
public class OrdersUserModel extends Orders { private Integer id; private String username; private Date birthday; private String sex; private String address; ... }
OrdersMapper.xml:
注意:这里使用的是resultType,要求OrdersUserModel的字段要和sql查询的field一样,要不查询出来的为null。如果不一样,使用sql语句别名,改为一样的。
<select id="queryOrdersAndUserModel" resultType="com.dmsd.pojo.OrdersUserModel"> SELECT orders.id , orders.number , USER.username, USER.sex, USER.address FROM orders, USER WHERE orders.user_id = USER.id </select>
测试方法:
@Test public void testqueryOrdersAndUserModel(){ List<OrdersUserModel> ordersUserModels = orderService.queryOrdersAndUserModel(); System.out.println(ordersUserModels); }
这样查询出来:
方法二、使用resultMap(association)
association用于映射一对一的关联查询。
订单实体:
public class Orders { private Integer id; private Integer userId; private String number; private Date createtime; private String note; private User user; .... }
用户实体:
public class User { private Integer id; private String username; private Date birthday; private String sex; private String address; ... }
orderMapper.xml:
resultMap参数说明:
- id指定查询列中的唯一标识,订单信息中的唯一标识,如果有多个列组成唯一标识,配置多个id。
- column:sql语句查询出的field
- property:与sql查询出的field 对应的实体字段
association参数说明:
- property:要关联查询的用户信息,本例中指Orders下的user属性。
- javaType:关联的属性的所属类
- id:关联查询用户的唯一标识
- column:sql语句查询出的field
- property:与sql查询出的field 对应的实体字段
<resultMap id="ordersMap" type="com.dmsd.pojo.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="com.dmsd.pojo.User"> <id column="user_id" property="id"/> <result column="username" property="username"/> <result column="sex" property="sex"/> <result column="address" property="address"/> </association> </resultMap> <select id="queryOrdersAndOrderDetailAndItems" resultMap="ordersMap"> SELECT orders.*, USER.username, USER.sex, USER.address FROM orders, USER WHERE orders.user_id = USER.id </select>
测试方法查询:
/** * 关联查询用户和订单 */ @Test public void testqueryOrdersAndOrderDetailAndItems(){ List<Orders> orders = orderService.queryOrdersAndOrderDetailAndItems(); System.out.println(orders); }
结果:
三、关联关系为:一对多查询
使用resultMap查询
需求:关联查询订单和订单明细,一个订单可以有多个订单明细
分析:因为一个订单可以有多个订单明细,在orders.java 类中添加private List<Orderdetail> orderdetails;
属性。
通过sql内连接就可以查出需要的数据。
orders.java:
public class Orders { private Integer id; private Integer userId; private String number; private Date createtime; private String note; private User user; private List<Orderdetail> orderdetails; //一个订单可以有多个明细 ... }
Orderdetail.java:
public class Orderdetail { private Integer id; private Integer ordersId; private Integer itemsId; private Integer itemsNum; ... }
然后写 OrderMapper.xml文件:
collection参数说明:
一对多的时候,用collection。
- property:将关联查询到多条记录映射到Orders哪个属性
- ofType:指定映射到list集合属性中pojo的类型
<resultMap id="OrderAndDetailMap" type="com.dmsd.pojo.Orders" > <id column="order_id" property="id"/> <result column="user_id" property="userId"/> <result column="number" property="number"/> <!--一个订单可以有多个订单明细,所以要使用collection--> <collection property="orderdetails" ofType="com.dmsd.pojo.Orderdetail"> <id column="detail_id" property="id"/> <result column="items_id" property="itemsId"/> <result column="items_num" property="itemsNum"/> </collection> </resultMap> <!--关联查询订单和订单明细,一个订单可以有多个订单明细--> <select id="queryOrdersAndOrderDetailMap" resultMap="OrderAndDetailMap"> SELECT o.id as order_id, o.user_id, o.number, d.id as detail_id, d.items_id, d.items_num FROM orders o, orderdetail d WHERE d.orders_id = o.id </select>
测试方法:
@Test public void testqueryOrdersAndOrderDetailMap(){ List<Orders> orders = orderService.queryOrdersAndOrderDetailMap(); System.out.println(orders); }
结果:
四、关联关系为:多对多查询
使用resultMap查询
需求:一个人可以买多种商品,一种商品也可以被多个人买,多对多
分析:通过关联查询可以查询出来。将用户信息映射到user中。
在user类中添加订单列表属性List orders,将用户创建的订单映射到orderslist在Orders中添加订单明细列表属性Listorderdetials,将订单的明细映射到orderdetials
在OrderDetail中添加Items属性,将订单明细所对应的商品映射到Items
user:添加订单列表属性List orders
public class User { private Integer id; private String username; private Date birthday; private String sex; private String address; private List<Orders> orders; //一个用户可以有多个订单 ... }
orders:添加订单明细列表属性Listorderdetials
public class Orders { private Integer id; private Integer userId; private String number; private Date createtime; private String note; private User user; private List<Orderdetail> orderdetails; //一个订单可以有多个明 ... }
orderdetail:添加Items属性
public class Orderdetail { private Integer id; private Integer ordersId; private Integer itemsId; private Integer itemsNum; private Items items; //一个订单明细,可以有1个物品
items:没做修改
public class Items { private Integer id; private String name; private Float price; private String pic; private Date createtime; private String detail;
UserMapper.xml:
<resultMap id="UserMap" type="com.dmsd.pojo.User"> <id column="id" property="id"/> <result column="username" property="username"/> <result column="sex" property="sex"/> <result column="address" property="address"/> <!--一个人可以有多个订单--> <collection property="orders" ofType="com.dmsd.pojo.Orders"> <id column="orders_id" property="id"/> <result column="number" property="number"/> <!--一个订单可以有多个订单详情--> <collection property="orderdetails" ofType="com.dmsd.pojo.Orderdetail"> <id column="detail_id" property="id"/> <result column="items_num" property="itemsNum"/> <!-- 一个订单详情只能有一个商品--> <association property="items" javaType="com.dmsd.pojo.Items"> <id column="items_id" property="id"/> <result column="detail" property="detail"/> <result column="name" property="name"/> <result column="price" property="price"/> </association> </collection> </collection> </resultMap> <select id="queryUserMap" resultMap="UserMap"> SELECT u.*, o.id as orders_id, o.number , d.id as detail_id, d.items_num, i.id as items_id, i.detail , i.`name`, i.price FROM `user` u, orders o, orderdetail d, items i WHERE u.id = o.user_id AND o.id = d.orders_id AND d.items_id = i.id </select>
测试:
@Test public void testqueryUserMap(){ List<User> users = userService.queryUserMap(); System.out.println(users); }
结果:
五、ResultType和ResultMap的区别
1.两者都是 mybatis sql查询的返回结果集
2.resultType:当使用resultType做SQL语句返回结果类型处理时,对于SQL语句查询出的字段在相应的pojo中必须有和它相同的字段对应,而resultType中的内容就是pojo在本项目中的位置。
因此对于单表查询的话用resultType是最合适的。但是,如果在写pojo时,不想用数据库表中定义的字段名称,也是可以使用resultMap进行处理对应的。多表连接查询时,若是一对一的连接查询,那么需要新建一个pojo,pojo中包括两个表中需要查询出的所有的字段,这个地方的处理方式通常为创建一个继承一个表字段的pojo,再在里面添加另外一个表内需要查询出的字段即可。若是一对多查询时,若是使用内连接查询,则很可能出现查询出的字段有重复。使用双重for循环嵌套处理即可。
3.resultMap:当使用resultMap做SQL语句返回结果类型处理时,通常需要在mapper.xml中定义resultMap进行pojo和相应表字段的对应。
resultMap对于一对一表连接的处理方式通常为在主表的pojo中添加嵌套另一个表的pojo,然后在mapper.xml中采用association节点元素进行对另一个表的连接处理。若是一对多的表连接方式,比如订单表和订单明细表即为一对多连接,若是不对sql语句进行处理,由于一个订单对应多条订单明细,因此查询出的结果对于订单表数据来说将会出现重复。
六、小结
- 先找对应关系
- 找主查询表
- 写sql语句
- 写映射实体 resultMap or resultType
- 写实体关系,如果是resultMap,一对一选择association,一对多选择collection。
- 完成测试。
摘自:https://blog.csdn.net/kisscatforever/article/details/79476614