一、前言
前面的时候,小编向大家介绍了Mybatis的使用,总结来说,Mybatis注重的是写sql语句。针对单表 的增删改查还是比较好写的,直接写出SQL语句可以了,但是如果遇到了多表的关联查询,可能就会复杂了点。下面小编就向大家介绍如何进行多表的复杂查询 。
二、关联关系为一对一查询
方法一 使用resultType
思路:创建一个大实体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参数说明:
1. id指定查询列中的唯一标识,订单信息中的唯一标识,如果有多个列组成唯一标识,配置多个id。
2. column:sql语句查询出的field
3. property:与sql查询出的field 对应的实体字段
association参数说明:
1.property:要关联查询的用户信息,本例中指Orders下的user属性。
2.javaType:关联的属性的所属类
3.id:关联查询用户的唯一标识
4.column:sql语句查询出的field
5.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。
1.property:将关联查询到多条记录映射到Orders哪个属性
2.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语句进行处理,由于一个订单对应多条订单明细,因此查询出的结果对于订单表数据来说将会出现重复。
六、小结
1.先找对应关系
2.找主查询表
3.写sql语句
4.写映射实体 resultMap or resultType
5.写实体关系,如果是resultMap,一对一选择association,一对多选择collection。
6.完成测试。