MyBatis多表映射

一、多表映射概念:

1.多表查询结果映射思路:

MyBatis思想是:数据库不可能永远是你所想或所需的那个样子。 我们希望每个数据库都具备良好的第三范式或BCNF范式,可惜它们并不都是那样。 如果能有一种数据库映射模式,完美适配所有的应用程序查询需求,那就太好了,而ResultMap就是MyBatis就是完美答案

2.实体类设计方案:

(1).多表关系回顾:

**a.一对一:**夫妻关系,人和身份证号

**b.一对多|多对一:**用户和用户的订单,锁和钥匙

**c.多对多:**老师和学生,部门和员工

(2).实体类设计关系(查询):(单向查看)

**a.对一:**夫妻一方对应另一方,订单对应用户都是对一关系

**实体类设计:**对一关系下,类中只要包含单个对方对象类型属性即可

java 复制代码
public class Customer {

  private Integer customerId;
  private String customerName;

}

public class Order {

  private Integer orderId;
  private String orderName;
  private Customer customer;// 体现的是对一的关系

}  

**b.对多:**用户对应的订单,讲师对应的学生或者学生对应的讲师都是对多关系

**实体类设计:**对多关系下,类中只要包含对方类型集合属性即可

java 复制代码
public class Customer {

  private Integer customerId;
  private String customerName;
  private List<Order> orderList;// 体现的是对多的关系
}

public class Order {

  private Integer orderId;
  private String orderName;
  private Customer customer;// 体现的是对一的关系
  
}

//查询客户和客户对应的订单集合  不要管!

多表结果实体类设计小技巧:

对一,属性中包含对方对象

对多,属性中包含对方对象集合

只有真实发生多表查询时,才需要设计和修改实体类,否则不提前设计和修改实体类

无论多少张表联查,实体类设计都是两两考虑

在查询映射的时候,只需要关注本次查询相关的属性,例如:查询订单和对应的客户,就不要关注客户中的订单集合

二、对一映射:

**1.需求说明:**根据ID查询订单,以及订单关联的用户的信息

2.OrderMapper接口:

java 复制代码
public interface OrderMapper {
  Order selectOrderWithCustomer(Integer orderId);
}

3.OrderMapper.xml配置文件:

XML 复制代码
<!-- 创建resultMap实现"对一"关联关系映射 -->
<!-- id属性:通常设置为这个resultMap所服务的那条SQL语句的id加上"ResultMap" -->
<!-- type属性:要设置为这个resultMap所服务的那条SQL语句最终要返回的类型 -->
<resultMap id="selectOrderWithCustomerResultMap" type="order">

  <!-- 先设置Order自身属性和字段的对应关系 -->
  <id column="order_id" property="orderId"/>

  <result column="order_name" property="orderName"/>

  <!-- 使用association标签配置"对一"关联关系 -->
  <!-- property属性:在Order类中对一的一端进行引用时使用的属性名 -->
  <!-- javaType属性:一的一端类的全类名 -->
  <association property="customer" javaType="customer">

    <!-- 配置Customer类的属性和字段名之间的对应关系 -->
    <id column="customer_id" property="customerId"/>
    <result column="customer_name" property="customerName"/>

  </association>

</resultMap>

<!-- Order selectOrderWithCustomer(Integer orderId); -->
<select id="selectOrderWithCustomer" resultMap="selectOrderWithCustomerResultMap">

  SELECT order_id,order_name,c.customer_id,customer_name
  FROM t_order o
  LEFT JOIN t_customer c
  ON o.customer_id=c.customer_id
  WHERE o.order_id=#{orderId}

</select>

对应关系可以参考下图:

4.Mybatis全局注册Mapper文件:

XML 复制代码
<!-- 注册Mapper配置文件:告诉Mybatis我们的Mapper配置文件的位置 -->
<mappers>

  <!-- 在mapper标签的resource属性中指定Mapper配置文件以"类路径根目录"为基准的相对路径 -->
  <mapper resource="mappers/OrderMapper.xml"/>

</mappers>

5.junit测试程序:

java 复制代码
@Slf4j
public class MyBatisTest {

    private SqlSession session;
    // junit会在每一个@Test方法前执行@BeforeEach方法

    @BeforeEach
    public void init() throws IOException {
        session = new SqlSessionFactoryBuilder()
                .build(
                        Resources.getResourceAsStream("mybatis-config.xml"))
                .openSession();
    }

    @Test
    public void testRelationshipToOne() {
    
      OrderMapper orderMapper = session.getMapper(OrderMapper.class);
      // 查询Order对象,检查是否同时查询了关联的Customer对象
      Order order = orderMapper.selectOrderWithCustomer(2);
      log.info("order = " + order);
    
    }

    // junit会在每一个@Test方法后执行@@AfterEach方法
    @AfterEach
    public void clear() {
        session.commit();
        session.close();
    }
}

**6.关键词:**在"对一"关联关系中,我们的配置比较多,但是关键词就只有association和javaType

三、对多映射:

1.需求说明:

查询客户和客户关联的订单信息

2.CustomerMapper接口:

java 复制代码
public interface CustomerMapper {

  Customer selectCustomerWithOrderList(Integer customerId);

}

3.CustomerMapper.xml文件:

XML 复制代码
<!-- 配置resultMap实现从Customer到OrderList的"对多"关联关系 -->
<resultMap id="selectCustomerWithOrderListResultMap"

  type="customer">

  <!-- 映射Customer本身的属性 -->
  <id column="customer_id" property="customerId"/>

  <result column="customer_name" property="customerName"/>

  <!-- collection标签:映射"对多"的关联关系 -->
  <!-- property属性:在Customer类中,关联"多"的一端的属性名 -->
  <!-- ofType属性:集合属性中元素的类型 -->
  <collection property="orderList" ofType="order">

    <!-- 映射Order的属性 -->
    <id column="order_id" property="orderId"/>

    <result column="order_name" property="orderName"/>

  </collection>

</resultMap>

<!-- Customer selectCustomerWithOrderList(Integer customerId); -->
<select id="selectCustomerWithOrderList" resultMap="selectCustomerWithOrderListResultMap">
  SELECT c.customer_id,c.customer_name,o.order_id,o.order_name
  FROM t_customer c
  LEFT JOIN t_order o
  ON c.customer_id=o.customer_id
  WHERE c.customer_id=#{customerId}
</select>

对应关系可以参考下图:

4.Mybatis全局注册Mapper文件:

XML 复制代码
<!-- 注册Mapper配置文件:告诉Mybatis我们的Mapper配置文件的位置 -->
<mappers>
  <!-- 在mapper标签的resource属性中指定Mapper配置文件以"类路径根目录"为基准的相对路径 -->
  <mapper resource="mappers/OrderMapper.xml"/>
  <mapper resource="mappers/CustomerMapper.xml"/>
</mappers>

5.junit测试程序:

java 复制代码
@Test
public void testRelationshipToMulti() {

  CustomerMapper customerMapper = session.getMapper(CustomerMapper.class);
  // 查询Customer对象同时将关联的Order集合查询出来
  Customer customer = customerMapper.selectCustomerWithOrderList(1);
  log.info("customer.getCustomerId() = " + customer.getCustomerId());
  log.info("customer.getCustomerName() = " + customer.getCustomerName());
  List<Order> orderList = customer.getOrderList();
  for (Order order : orderList) {
    log.info("order = " + order);
  }
}

**6.关键词:**在"对多"关联关系中,同样有很多配置,但是提炼出来最关键的就是collection和ofType

四、多表映射总结:

1.多表映射优化:

setting属性 属性含义 可选值 默认值
autoMappingBehavior 指定MyBatis应如何自动映射列到字段或属性。 NONE 表示关闭自动映射;PARTIAL只会自动映射没有定义嵌套结果映射的字段。 FULL会自动映射任何复杂的结果集(无论是否嵌套) NONE, PARTIAL, FULL PARTIAL

可以将autoMappingBehavior设置为full,进行多表resultMap映射的时候可以省略符合列和属性命名映射规则(列名=属性名,或者开启驼峰映射也可以自定映射)的result标签

修改mybati-sconfig.xml:

XML 复制代码
<!--开启resultMap自动映射 -->
<setting name="autoMappingBehavior" value="FULL"/>

修改teacherMapper.xml:

XML 复制代码
<resultMap id="teacherMap" type="teacher">
    <id property="tId" column="t_id" />
    <!-- 开启自动映射,并且开启驼峰式支持!可以省略 result!-->
<!--        <result property="tName" column="t_name" />-->
    <collection property="students" ofType="student" >
        <id property="sId" column="s_id" />
<!--            <result property="sName" column="s_name" />-->
    </collection>
</resultMap>

2.多表映射总结:

关联关系 配置项关键词 所在配置文件和具体位置
对一 association标签/javaType属性/property属性 Mapper配置文件中的resultMap标签内
对多 collection标签/ofType属性/property属性 Mapper配置文件中的resultMap标签内
相关推荐
CopyLower28 分钟前
深入理解 MyBatis 的缓存机制:一级缓存与二级缓存
spring·缓存·mybatis
秋恬意5 小时前
什么是MyBatis?MyBatis的优缺点?
mybatis
编程、小哥哥7 小时前
设计模式之代理模式(模拟mybatis-spring中定义DAO接口,使用代理类方式操作数据库原理实现场景)
设计模式·mybatis·代理模式
Nu11PointerException8 小时前
JAVA笔记 | 策略模式+枚举Enum简单实现策略模式(可直接套用)
java·spring boot·spring·java-ee·mybatis·个人开发·策略模式
jakeswang1 天前
spring循环依赖以及MyBatis-Plus的继承特性导致循环依赖自动解决失效
java·spring·mybatis
雷神乐乐1 天前
MyBatis中的${}和#{}区别
数据库·sql·mybatis·javaweb
踩着上帝的小丑1 天前
mybatis学习(四)
windows·学习·mybatis
YaYicho1 天前
Mybatis入门
mybatis
catoop1 天前
对比 MyBatis 批处理 BATCH 模式与 INSERT INTO ... SELECT ... UNION ALL 进行批量插入
mybatis·batch