在《MyBatis一对一关联查询》教程中学习了 MyBatis 如何处理一对一级联查询,那么 MyBatis 又是如何处理一对多级联查询的呢?在实际生活中一对多级联关系有许多,例如一个用户可以有多个订单,而一个订单只属于一个用户。

下面以用户和订单之间的关系为例讲解一对多级联查询(实现“根据 uid 查询用户及其关联的订单信息”的功能)的处理过程,读者只需参考该实例即可学会一对多级联查询的 MyBatis 实现。

1)创建数据表

本实例需要两张数据表,一张是用户表 user,一张是订单表 orders,这两张表具有一对多的级联关系。user 表在前面已创建,orders 表的创建代码如下:

  1. CREATE TABLE orders (
  2. id tinyint(2) NOT NULL AUTO_INCREMENT,
  3. ordersn varchar(10) DEFAULT NULL,
  4. user_id tinyint(2) DEFAULT NULL,
  5. PRIMARY KEY (id)
  6. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

    2)创建持久化类

    在 myBatisDemo02 应用的 com.po 包中创建数据表 orders 对应的持久化类 Orders,user 表对应的持久化类 MyUser 在前面已创建,但需要为 MyUser 添加如下属性:
    // 一对多级联查询,用户关联的订单
    private List ordersList;
    同时,需要为该属性添加 setter 和 getter 方法。

Orders 类的代码如下:

  1. package com.po;

  2. public class Orders {
  3. private Integer id;
  4. private String ordersn;

  5. public Integer getId() {
  6. return id;
  7. }

  8. public void setId(Integer id) {
  9. this.id = id;
  10. }

  11. public String getOrdersn() {
  12. return ordersn;
  13. }

  14. public void setOrdersn(String ordersn) {
  15. this.ordersn = ordersn;
  16. }

  17. @Override
  18. public String toString() {
  19. return “Orders[id=” + id + “,ordersn=” + ordersn + “]”;
  20. }
  21. }

    3)创建映射文件

    在 myBatisDemo02 应用的 com.mybatis 中创建两张表对应的映射文件 UserMapper.xml 和 OrdersMapper.xml。映射文件 UserMapper.xml 在前面已创建,但需要添加以下配置才能实现一对多级联查询(根据 uid 查询用户及其关联的订单信息):

  22. <?xml version=”1.0” encoding=”UTF-8”?>

  23. <!DOCTYPE mapper
  24. PUBLIC “-//mybatis.org//DTD Mapper 3.0//EN”
  25. http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  26. <mapper namespace=”com.mybatis.mapper.UserMapper”>
  27. <resultMap type=”com.po.MyUser” id=”userAndOrders1”>
  28. <id property=”uid” column=”uid” />
  29. <result property=”uname” column=”uname” />
  30. <result property=”usex” column=”usex” />
  31. <collection property=”ordersList” ofType=”com.po.Orders”
  32. column=”uid” select=”com.dao.OrdersDao.selectOrdersByld” />
  33. <select id=”selectUserOrdersById1” parameterType=”Integer”
  34. resultMap=”userAndOrders1”>
  35. select * from user where uid = #{id}
  36. <resultMap type=”com.po.MyUser” id=”userAndOrders2”>
  37. <id property=”uid” column=”uid” />
  38. <result property=”uname” column=”uname” />
  39. <result property=”usex” column=”usex” />
  40. <collection property=”ordersList” ofType=”com.po.Orders”>
  41. <id property=”id” column=”id” />
  42. <result property=”ordersn” column=”ordersn” />
  43. <select id=”selectUserOrdersById2” parameterType=”Integer”
  44. resultMap=”userAndOrders2”>
  45. select u.*,o.id, o.ordersn from user u, orders o where u.uid
  46. = o.user_id and
  47. u.uid=#{id}
  48. <select id=”selectUserOrdersById3” parameterType=”Integer”
  49. resultType=”com.pojo.SelectUserOrdersById”>
  50. select u.*, o.id, o.ordersn from user u, orders o where
  51. u.uid = o.user_id
  52. and u.uid=#{id}

OrdersMapper.xml 的配置代码如下:

  1. <?xml version=”1.0” encoding=”UTF-8”?>
  2. <!DOCTYPE mapper
  3. PUBLIC “-//mybatis.org//DTD Mapper 3.0//EN”
  4. http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  5. <mapper namespace=”com.dao.OrdersDao”>
  6. <select id=”selectOrdersById” resultType=”com.po.Orders”
  7. parameterType=”Integer”>
  8. select * from orders where user_id=#{id}
  9. 4)创建 POJO 类

    在 myBatisDemo02 应用的 com.pojo 包中创建在第 3 步中使用的 POJO 类 com.pojo. SelectUserOrdersById。

SelectUserOrdersById 的代码如下:

  1. package com.po;

  2. public class SelectUserOrdersById {
  3. private Integer uid;
  4. private String uname;
  5. private String usex;
  6. private Integer id;
  7. private String ordersn;

  8. // 省略setter和getter方法
  9. @Override
  10. public String toString() { // 为了方便查看结果,重写了toString方法
  11. return “User[uid=” + uid + “,uname=” + uname + “,usex=” + usex
    • “,oid=” + id + “,ordersn=” + ordersn + “]”;
  12. }
  13. }

    5)创建数据操作接口

    在 myBatisDemo02 应用的 com.dao 包中创建第 3 步中映射文件对应的数据操作接口 OrdersDao 和 UserDao。

OrdersDao 的代码如下:

  1. package com.dao;

  2. import java.util.List;
  3. import org.apache.ibatis.annotations.Mapper;
  4. import org.springframework.stereotype.Repository;
  5. import com.po.Orders;

  6. @Repository(“ordersDao”)
  7. @Mapper
  8. public interface OrdersDao {
  9. public List selectOrdersById(Integer uid);
  10. }

UserDao 接口在前面已创建,这里只需添加如下接口方法:

  1. package com.dao;

  2. import java.util.List;
  3. import java.util.Map;

  4. import org.apache.ibatis.annotations.Mapper;
  5. import org.springframework.stereotype.Repository;

  6. import com.po.MyUser;
  7. import com.po.SelectUserOrdersById;

  8. @Repository(“userDao”)
  9. @Mapper
  10. public interface UserDao {

  11. public MyUser selectOrdersById1(Integer uid);

  12. public MyUser selectOrdersById2(Integer uid);

  13. public List selectOrdersById3(Integer uid);
  14. }

    6)调用接口方法及测试

    在 myBatisDemo02 应用的 com.controller 包中创建 OneToMoreController 类,在该类中调用第 5 步的接口方法,同时创建测试类 TestOneToMore。

OneToMoreController 的代码如下:

  1. @Controller(“oneToMoreController”)
  2. public class oneToMoreController {
  3. @Autowired
  4. private UserDao userDao;
  5. public void test(){
  6. //查询一个用户及订单信息
  7. MyUser auser1 = userDao.selectUserOrderById1(1);
  8. System.out.println(auser1);
  9. System.out.println(“=============================”);
  10. MyUser auser2 = userDao.selectUserOrderById2(1);
  11. System.out.println(auser2);
  12. System.out.println(“=============================”);
  13. List auser3 = userDao.selectUserOrdersById3(1);
  14. System.out.println(auser3);
  15. System.out.println(“=============================”);
  16. }
  17. }

TestOneToMore 的代码如下:

  1. public class TestOneToMore {
  2. public static void main(String[] args) {
  3. ApplicationContext appcon = new ClassPathXmlApplicationContext(“applicationContext.xml”);
  4. OneToMoreController otm = (OneToMoreController)appcon.getBean(“oneToMoreController”);
  5. otm.test();
  6. }
  7. }

测试类的运行结果如图 1 所示。

28-MyBatis一对多关联查询(级联查询) - 图1
图 1 一对多级联查询结果