商品订单模型
一个用户可以下n个订单,一个订单只能属于一个用户。
一个订单可以有多个订单详情,订单和订单详情是一对多的关系。
一个订单中可以有多个商品,一个商品也可以属于多个订单,订单和商品多对多的关系
关联查询几个需要注意的细节
1.超过三个表禁止 join。需要 join 的字段,数据类型必须绝对一致;多表关联查询时,保证被关联的字段需要有索引
2.不得使用外键与级联,一切外键概念必须在应用层解决
3.字段允许适当冗余,以提高查询性能,但必须考虑数据一致
关联方式
关联元素:association用于表示一对一关系,collection用于表示一对多关系;
- 嵌套结果:使用嵌套结果映射来处理重复的联合结果的子集
- 嵌套查询:通过执行另外一个 SQL 映射语句来返回预期的复杂类型
4.1 一对一查询
查询所有订单信息,关联查询下单用户信息。
SELECT
o.id,
o.user_id,
o.status,
o.amount,
o.create_time,
u.user_name,
u.address,
u.sex,
u.birthday
FROM
t_order o
JOIN t_user u ON u.id = o.user_id
主信息:订单信息 t_order
从信息:用户信息 t_user
4.1.1 使用 resultType
使用resultType进行结果映射。
1.分析
1、如果使用resultType进行结果映射,则查询的列名和映射pojo的属性名称要一致。
2、关联查询的结果集,既包含订单信息,又包含用户信息。使用订单po或者用户po类都无法完成结果映射。
3、需要定义扩展po类,此类继承订单信息po类,同时还要包括用户信息:
2.定义pojo 扩展类
扩展Po类中应该包括上边sql查询出来的所有字段,如下:
package com.xa02.domain;
import java.util.Date;
public class OrderExtend extends OrderInfo{
private String userName;
private String sex;
private Date birthday;
private String address;
......
}
OrdersExt类继承OrderInfo类后,便会继承OrderInfo类的所有字段,除此之外只需要定义用户信息字段即可。
3.Mapper文件
在OrderMapper.xml中,添加以下代码:
<select id="selectList" resultType="OrderExtend">
SELECT
o.id,
o.user_id,
o.status,
o.amount,
o.create_time,
u.user_name,
u.address,
u.sex,
u.birthday
FROM
t_order o
JOIN t_user u ON u.id = o.user_id
</select>
4.Mapper接口
在OrderMapper接口中,添加以下接口方法:
public interface OrderMapper {
List<OrderExtend> selectList();
}
5.测试代码
在UserMapperTest测试类中,添加测试代码:
@Test
public void selectList(){
SqlSession sqlSession = sqlSessionFactory.openSession();
try{
OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);
List<OrderExtend> OrderExtendList = orderMapper.selectList();
System.out.println("selectList....."+OrderExtendList);
}finally{
sqlSession.close();
}
}
6.小结
1、一对一关联查询时,可以定义专门的扩展po类作为输出结果类型。
2、该扩展po类中定义了sql查询结果集所有的字段对应的属性。
3、此方法较为简单,企业中使用普遍。
4.1.2 使用resultMap
使用resultMap进行结果映射,定义专门的resultMap用于映射一对一查询结果。
1.修改pojo类
在 OrderExtend 类中加入 User 属性,user 属性中用于存储关联查询的用户信息,因为订单关联查询用户是一对一关系,所以这里使用单个User对象存储关联查
询的用户信息。
public class OrderExtend extends OrderInfo{
private UserInfo user;
public UserInfo getUser() {
return user;
}
public void setUser(UserInfo user) {
this.user = user;
}
@Override
public String toString() {
return "OrderExtend{" +
"user=" + user +
'}';
}
}
2.Mapper映射文件
在OrderMapper.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.xa02.mapper.OrderMapper">
<!-- 定义resultMap:将查询的列名和映射的pojo的属性名做一个对应关系 -->
<!--
1.id 指定 resultMap的唯一表示。
2.type:指定查询结果要映射的pojo类型。
-->
<resultMap id="orderResultMap" type="OrderExtend">
<!--
id标签:映射查询结果的唯一列(主键列)
column:查询sql的列名
property:映射结果的属性名
-->
<id column="id" property="id"/>
<!-- result标签:映射查询结果pojo的普通列 -->
<result column="user_id" property="userId"/>
<result column="status" property="status"/>
<result column="amount" property="amount"/>
<result column="create_time" property="createTime"/>
<!-- 一对一 映射 -->
<association property="user" javaType="UserInfo">
<id column="id" property="id"/>
<result column="user_name" property="userName"/>
<result column="sex" property="sex"/>
<result column="birthday" property="birthday"/>
<result column="address" property="address"/>
</association>
</resultMap>
<!-- 模糊查询 -->
<select id="selectList" resultMap="orderResultMap">
SELECT
o.id,
o.user_id,
o.status,
o.amount,
o.create_time,
u.user_name,
u.address,
u.sex,
u.birthday
FROM
t_order o
JOIN t_user u ON u.id = o.user_id
</select>
</mapper>
association:表示进行一对一关联查询映射
property:表示关联查询的结果存储在OrderExtend的user属性中
javaType:表示关联查询的映射结果类型
columnPrefix :查询列的前缀,配置前缀后,在子标签配置 result 的 column 时可以省略前缀
使用resultMap进行结果映射时,具体是使用association完成关联查询的映射,将关联查询信息映射到pojo对象中。
开发小技巧
1.resultMap可以通过使用extends实现继承关系,简化很多配置工作量;
2.关联的表查询的类添加前缀是编程的好习惯;
3.通过添加完整的命名空间,可以引用其他xml文件的resultMap;
4.2 一对多查询
查询所有用户信息及用户关联的订单信息。
SELECT
u.id,
u.user_id,
u.status,
u.amount,
u.create_time,
o.id,
o.user_name,
o.address,
o.sex,
o.birthday
FROM
t_user o
left join t_order u ON o.id = u.user_id
主信息:用户信息 t_user
从信息:订单信息 t_order
在一对多关联查询时,只能使用resultMap进行结果映射。
1、一对多关联查询时,sql查询结果有多条,而映射对象是一个。
2、resultType完成结果映射的方式的一条记录映射一个对象。
3、resultMap完成结果映射的方式是以[主信息]为主对象,[从信息]映射为集合或者对象,然后封装到主对象中。
在User类中加入List orders属性
public class UserInfo {
private Long id;
private String userName;
private String sex;
private Date birthday;
private String address;
private List<OrderInfo> orderInfoList;
1.Mapper映射文件
<?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.xa02.mapper.UserMapper">
<!-- 定义resultMap:将查询的列名和映射的pojo的属性名做一个对应关系 -->
<!--
1.id 指定 resultMap的唯一表示。
2.type:指定查询结果要映射的pojo类型。
-->
<resultMap id="userResultMap" type="UserInfo">
<!--
id标签:映射查询结果的唯一列(主键列)
column:查询sql的列名
property:映射结果的属性名
-->
<id column="id" property="id"/>
<!-- result标签:映射查询结果pojo的普通列 -->
<result column="user_name" property="userName"/>
<result column="sex" property="sex"/>
<result column="birthday" property="birthday"/>
<result column="address" property="address"/>
<!-- 一对多关联映射 -->
<collection property="orderInfoList" ofType="OrderInfo">
<id column="id" property="id"/>
<!-- result标签:映射查询结果pojo的普通列 -->
<result column="user_id" property="userId"/>
<result column="status" property="status"/>
<result column="amount" property="amount"/>
<result column="create_time" property="createTime"/>
</collection>
</resultMap>
<!-- 模糊查询 -->
<select id="selectList" resultMap="userResultMap">
SELECT
u.id,
u.user_id,
u.status,
u.amount,
u.create_time,
o.id,
o.user_name,
o.address,
o.sex,
o.birthday
FROM
t_user o
left join t_order u ON o.id = u.user_id
</select>
</mapper>
Collection标签:定义了一对多关联的结果映射。
property=*"orderInfoList:*关联查询的结果集存储在User对象的上的属性。
ofType=*“OrderInfo”:*指定关联查询的结果集中的对象类型即List中的对象类型。此处可以使用别名,也可以使用全限定名。
4.3 多对多关联
要实现多对多的关联,需要满足如下两个条件
先决条件一:多对多需要一种中间表建立连接关系
先决条件二:多对多关系是由两个一对多关系组成的,一对多可以也可以用两种方式实现;