**高级映射:主要应用与复杂的sql操作将复杂的查询结果映射到对应的实体类中
1、订单商品数据模型**
1.1、数据模型分析思路
1、每张表记录的数据内容
分模块对每张表记录的数据内容, 相当于学习系统需求(功能)的过程。
2、每张表重要字段的设置
非空字段、外键字段
3、数据库级别标语表之间的关系
外键关系
4、表与表之间的业务关系
一定要建立在某个业务意义的基础上
1.2、数据模型分析
商品信息 订单明细 订单 用户信息
1.3、表与表的业务关系
在分析表与表之间的业务关系时需要建立在某个业务意义基础上去分析,先分析数据库级别中的表之间的业务关系。
用户和订单user和orders
user—>orders:一个用户可以创建多个订单,一对多
orders---->user:一个订单只由一个用户创建,一对一
orders–>order_detail:一个订单可以包括多个订单明细,因为一个订单可以购买多个商品,每个商品的购买信息在order_detail表中记录,一对多关系。
order_detail–>orders:一个订单明细只能包括在一个订单中,一对一。
order_detail和items:
order_detail–>items:一个订单明细只对应一个商品信息,一对一。
items–>ordertail:一个商品可以包括在多个订单明细中。一对多。
2、一对一查询
2.1、需求
查询订单信息,关联查询创建订单的用户信息
2.2、使用resultType映射结果到实体类
2.2.1、sql语句,
确定查询的主表:订单表
确定查询的关联表:用户表
关联查询,内链接还是外连接?
由于orders表中有一个外键(user_id),通过外键关联查询用户表只能查询到一条记录,使用内链接,
SELECT
orders.*,
`user`.userName,
`user`.address
FROM
orders,
`user`
WHERE
orders.user_id = `user`.id:
2.2.2、创建pojo
将查询结果映射到pojo中,pojo需包含所有查询列名
/**
* 订单扩展类
* @author guai
*
*/
public class OrdersCustom extends Orders {
private String userName;
private String address;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
2.2.3、mapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.shuai.mapper.OrdersMapperCustom">
<!-- 查询订单关联查询用户信息 -->
<select id="selectOrdersCustom" resultType="com.shuai.po.OrdersCustom">
SELECT orders.*, `user`.userName, `user`.address FROM orders, `user`
WHERE orders.user_id = `user`.id;
</select>
</mapper>
2.2.4、mapper接口
public interface OrdersMapperCustom {
//查询订单关联查询用户信息
public List<OrdersCustom> selectOrdersCustom() throws Exception;
}
2.3、resultMap的使用
2.3.1、需求:查询用户订单信息及用户基本信息
使用resultMap将查询结果中的订单信息映射到Orders()对象中,在orders类中添加User属性,并将查询结果中关于user的信息映射到orders对象中的user属性中。
2.3.2、创建orders类
public class Orders {
private Integer id;
private Integer userId;
private Integer number;
private Date createTime;
private String note;
//User实体类
private User user;
......
}
2.3.3、mapper.xml
1、定义resultMap映射查询结果
注意:在设计实体类时,属性名应该与表中例名对应,这样就可以将查询结果自动映射到实体类的对应属性上。
<!-- 定义一个resultMap -->
<resultMap type="com.shuai.po.Orders" id="OrdersCustomResultMap">
<!-- 配置映射的订单信息 -->
<!-- id:指定查询查询列中的唯一标识 ,可配置多个(即由多个列组成唯一标识)
column:表中指定列名,property:实体类中属性名-->
<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:用于映射关联查询单个对象的信息 -->
<association property="user" javaType="com.shuai.po.User">
<!-- id:关联查询用户的唯一标识
column:指定唯一标识用户信息的列
javaType:映射到user的哪个属性
-->
<id column="user_id" javaType="id"/>
<result column="userName" property="userName"/>
<result column="address" property="address"/>
</association>
</resultMap>
2、statement定义
<select id="selectOrdersCustomResultMap" resultMap="OrdersCustomResultMap">
SELECT orders.*,`user`.userName, `user`.address FROM orders, `user` WHERE orders.user_id = `user`.id;
</select>
2.4、resultType和resultMap实现一对一查询
实现一对一查询:
使用resultType查询较为简单,如果pojo中没有包括查询出来的列名,需要增加列名对应的属性,即可完成映射;
如果对查询结果的没有特殊要求使用resultType较为简单
使用resultMap需单独定义resultMap,较为麻烦,如果有查询结果的特殊要求,使用resultMap可以完成将关联结果映射到pojo属性中。
3、一对多查询
3.1、需求
查询订单及订单明细
3.2、sql
确定查询主表:订单表
确定查询关联表:订单详细信息表,用户表
SELECT orders.*, user
.userName, user
.address, order_detail.itemsId FROM orders, order_detail,user
WHERE orders.id=order_detail.ordersId and orders.userId = user
.id;
3.3、分析
在实际购物中一次可能购买多个商品,即一个订单对应多个购买商品,即一个orders对应多个orderDetails。
实现: 使用resultType将上边的查询结果映射到pojo中,订单的信息是重复的记录 。需在order.java类中添加ListorderDetails属性。
最终会将订单信息映射到orders中,订单所对应的订单明细映射到orders中的orderDetails属性中。
映射成的orders记录为一条(orders信息不重复)每个orders中的orderDetails属性中存储了该订单所对应的订单明细。
3.4、在orders实体中添加list orderDetai订单明细属性。
public class Orders {
private Integer id;
private Integer userId;
private Integer number;
private Date createTime;
private String note;
//用户信息
private User user;
//订单详细信息
private List<OrderDetail> orderDetails;
......
}
3.5、mapper.xml
//此为查询订单及用户基本信息的resultMap
<resultMap type="com.shuai.po.Orders" id="OrdersCustomResultMap">
<!-- 配置映射的订单信息 -->
<!-- id:指定查询查询列中的唯一标识 ,可配置多个(即由多个列组成唯一标识)
column:表中指定列名,property:实体类中属性名-->
<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:用于映射关联查询单个对象的信息 -->
<association property="user" javaType="com.shuai.po.User">
<!-- id:关联查询用户的唯一标识
column:指定唯一标识用户信息的列
javaType:映射到user的哪个属性
-->
<id column="user_id" javaType="id"/>
<result column="userName" property="userName"/>
<result column="address" property="address"/>
</association>
</resultMap>
<!-- 查询订单关联用户及订单明细的resultMap
使用继承,继承OrdersCustomResultMap,不用再配置订单信息和用户信息
-->
<resultMap type="com.shuai.po.Orders" id="ordersMap" extends="OrdersCustomResultMap">
<!-- 订单信息和用户信息可以通过继承得来 -->
<!--
用于映射关联查询多个对象的信息 ,
订单明细 使用collection映射,
property:将关联查询到的多条记录映射到 orders中指定的属性中
ofType:指定映射到集合属性中pojo类型 -->
<collection property="orderDetails" ofType="com.shuai.po.OrderDetail">
<id column="detailId" property="id" />
<result column="itemsId" property="itemsId"/>
</collection>
</resultMap>
<!-- 查询订单关联用户及订单明细,使用resultMap -->
<select id="selectOrders" resultMap="ordersMap"> SELECT orders.*, `user`.userName,
`user`.address, order_detail.id detailId, order_detail.itemsId FROM orders,
order_detail, `user` WHERE orders.id=order_detail.ordersId and orders.userId =
`user`.id;
</select>
3.6、mapper接口
//查询订单 关联用户及订单明细
public List<Orders> selectOrders()throws Exception
3.7、小结
mybatis中resultType使用collection对关联查询的多条记录映射到一个list集合属性中
若使用resultType实现:
将订单明细映射到orders中的orderdetails中,需要自己处理,使用双重循环遍历,去掉重复记录,将订单明细放在orderDetails中
//商品信息实体:
public class OrderDetail {
private Integer id;
private Integer ordersId;
private Integer itemsId;
private Integer number;
private Items items;
...
}
//订单实体:
public class Orders {
private Integer id;
private Integer userId;
private Integer number;
private Date createTime;
private String note;
// 用户信息
private User user;
....
}
4、多对多查询
4.1、需求
查询用户及用户该买的商品信息。
4.2、分析
查询主表是用户表
关联表:由于用户和商品没有之间关联,通过订单和订单明细进行关联,所以关联表orders、orderDetail、items
SELECT orders.*, order_detail.id detailId, order_detail.itemsId, items.`name`, `user`.userName, `user`.address
FROM orders, order_detail, `user`, items
WHERE orders.id=order_detail.ordersId and orders.userId = `user`.id and order_detail.itemsId=items.id;
4.3、映射思路
将用户信息映射到user中
在user类中添加订单列表属性List orderList。
在orders中添加订单明细表属性List orderDetails。
在orderDetails中提娜佳items属性
4.4、mapper.xml
<!-- 查询用户及购买的商品 -->
<resultMap type="com.shuai.po.User" id="usersItems">
<!-- 用户 -->
<id column="id" property="id"/>
<id column="userName" property="userName"/>
<id column="address" property="address"/>
<!-- 订单 -->
<collection property="orders" ofType="com.shuai.po.Orders">
<id column="ordersId" property="id"/>
<result column="number" property="number"/>
<result column="createTime" property="createTime"/>
<!-- 订单明细 -->
<collection property="orderDetails" ofType="com.shuai.po.OrderDetail">
<id column="detailId" property="id" />
<!-- 商品信息 -->
<association property="items" javaType="com.shuai.po.Items">
<id column="itemsId" property="id"/>
<result column="name" property="name"/>
</association>
</collection>
</collection>
</resultMap>
<!-- 用户及所购商品信息,使用resultMap -->
<select id="selectUsersItems" resultMap="usersItems">SELECT orders.id ordersId,
orders.createTime, orders.number, order_detail.id detailId, order_detail.itemsId,
items.`name`, `user`.id, `user`.userName, `user`.address FROM orders, order_detail,
`user`, items WHERE orders.id=order_detail.ordersId and orders.userId = `user`.id
and order_detail.itemsId=items.id;
</select>
4.5、mapper接口
//查询用户的 订单信息
public List<User> selectUsersItems()throws Exception;
4.6、小结
1、当查询结果较为复杂涉及多个表时,使用mapper与实体类映射更加方便。
2、
与 的区别 association 用于映射关联查询单个对象的信息 而collection用于映射关联查询多个对象的信息 及映射的实体类属性为集合类型。