10.MyBatis的多表查询
关系型数据库表关系分为
* 一对一
* 一对多
* 多对多
举例
- 人和身份证号就是一对一
一个人只能有一个身份证号
一个身份证号只能属于一个人 - 用户和订单就是一对多,订单和用户就是多对一
一个用户可以下多个订单
多个订单属于同一个用户 - 学生和课程就是多对多
一个学生可以选修多门课程
一个课程可以被多个学生选修 - 特例
一个订单只从属于一个用户,所以mybatis将多对一看成了一对一
1.一对一关联查询
- 一对一查询模型
用户表和订单表的关系为,一个用户有多个订单,一个订单只从属于一个用户
一对一查询的需求:查询所有订单,与此同时查询出每个订单所属的用户
-
一对多查询语句
SELECT *,o.id oid FROM USER u LEFT JOIN orders o ON u.`id` = o.`uid`;
1.1代码实现
(1)Order实体
private Integer id;
private String orderTime;
private Double total;
private Integer uid;
//引入User对象
private User user;
(2)OrderMapper接口
public interface OrdersMapper {
// 查询用户订单
List<Orders> findOrder();
}
(3)OrderMapper.xml映射
- 一对一(多对一)使用association标签关联
<mapper namespace="com.lagou.mapper.OrdersMapper">
<resultMap id="orderMapper" type="orders">
<id property="id" column="id"></id>
<result property="orderTime" column="orderTime"></result>
<result property="total" column="total"></result>
<result property="uid" column="uid"></result>
<!--
一对一(多对一)使用association标签关联
property="user" 封装实体的属性名
javaType="user" 封装实体的属性类型
-->
<collection property="user" javaType="com.lagou.domain.User">
<id property="id" column="uid"></id>
<result property="username" column="username"></result>
<result property="birthday" column="birthday"></result>
<result property="sex" column="sex"></result>
<result property="address" column="address"></result>
</collection>
</resultMap>
<select id="findOrder" resultMap="orderMapper">
select *,u.id as uid from orders o left join `user` u on u.id =o.uid
</select>
</mapper>
(4)测试代码
@Test
public void test2() throws IOException {
InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
OrdersMapper ordersMapper = sqlSession.getMapper(OrdersMapper.class);
List<Orders> orders = ordersMapper.findOrder();
for (Orders order : orders) {
System.out.println(order);
}
sqlSession.close();
}
-
测试结果
2.一对多关联查询
-
一对多模型
用户表和订单表的关系为,一个用户有多个订单,一个订单只从属于一个用户
一对多查询的需求:查询所有用户,与此同时查询出该用户具有的订单 -
一对多查询语句
SELECT *,o.id oid FROM USER u LEFT JOIN orders o ON u.`id` = o.`uid`;
2.1代码实现
(1)User实体类
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
代表当前用户具备的订单列表
public List<Orders> ordersList;
(2)UserMapper接口
// 查询用户的订单信息
List<User> findUserOrder();
(3)UserMapper.xml映射
- collection:一对多使用collection标签
- property=“ordersList” :封装到集合的属性名
- ofType=“order” : 封装集合的泛型类型
<?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.lagou.mapper.UserMapper">
<resultMap id="userMapper" type="user">
<id property="id" column="id"></id>
<result property="username" column="username"></result>
<result property="birthday" column="birthday"></result>
<result property="sex" column="sex"></result>
<result property="address" column="address"></result>
<!-- collection:一对多使用collection标签
property="ordersList" :封装到集合的属性名
ofType="order" : 封装集合的泛型类型
-->
<collection property="ordersList" ofType="com.lagou.domain.Orders">
<id property="id" column="oid"></id>
<result property="orderTime" column="orderTime"></result>
<result property="total" column="total"></result>
<result property="uid" column="uid"></result>
</collection>
</resultMap>
<select id="findUserOrder" resultMap="userMapper">
SELECT u.*,o.id oid , o.total, o.ordertime FROM USER u LEFT JOIN orders o ON u.`id` = o.`uid`;
</select>
</mapper>
(4)测试代码
@Test
public void test3() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
// 当前返回的 其实是基于UserMapper所产生的代理对象:底层:JDK动态代理 实际类型:proxy
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> users = mapper.findUserOrder();
for (User people : users) {
System.out.println(people);
}
sqlSession.close();
}
3.多对多关联查询
-
多对多查询的模型
用户表和角色表的关系为,一个用户有多个角色,一个角色被多个用户使用。
多对多查询的需求:查询所有用户同时查询出该用户的所有角色 -
查询语句
SELECT u.*,r.id rid,r.rolename,r.roleDesc FROM `user` u LEFT JOIN sys_user_role ur on u.id = ur.userid
LEFT JOIN sys_role r on ur.roleid = r.id ;
3.1代码实现
(1)User和Role 实体
public class Role {
private Integer id;
private String rolename;
private String roleDesc;
}
public class User {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
// 代表当前用户具备的订单列表
public List<Orders> ordersList;
//代表当前用户关联的角色列表
private List<Role> roleList;
}
(2)UserMapper接口
// 查询所有用户对应的角色
List<User> findAllUserWithRole();
(3)UserMapper.xml映射
<resultMap id="getUserWithRole" type="user">
<id property="id" column="id"></id>
<result property="username" column="username"></result>
<result property="birthday" column="birthday"></result>
<result property="sex" column="sex"></result>
<result property="address" column="address"></result>
<collection property="roleList" ofType="com.lagou.domain.Role">
<id property="id" column="rid"></id>
<result property="rolename" column="rolename"></result>
<result property="roleDesc" column="roleDesc"></result>
</collection>
</resultMap>
<select id="findAllUserWithRole" resultMap="getUserWithRole">
SELECT u.*,r.id rid,r.rolename,r.roleDesc FROM `user` u LEFT JOIN sys_user_role ur on u.id = ur.userid LEFT JOIN sys_role r on ur.roleid = r.id ;
</select>
(4)测试代码
@Test
public void test4() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
// 当前返回的 其实是基于UserMapper所产生的代理对象:底层:JDK动态代理 实际类型:proxy
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> users = mapper.findAllUserWithRole();
for (User people : users) {
System.out.println(people);
}
sqlSession.close();
}
(5)测试结果
4.小结
MyBatis多表配置方式
* 多对一(一对一)配置:使用<resultMap>+<association>做配置
* 一对多配置:使用<resultMap>+<collection>做配置
* 多对多配置:使用<resultMap>+<collection>做配置
* 多对多的配置跟一对多很相似,难度在于SQL语句的编写。