文章目录
- 一、多表映射概念
 - 二、对一映射
 - 三、对多映射
 - 四、多表映射总结
 - 4.1 多表映射优化
 - 4.2 多表映射总结
 
一、多表映射概念
- 多表关系:
 
- 一对一
 - 一对多 | 多对一
 - 多对多
 
- 一个 客户 对应 多个订单
 - 一个订单 对应 一个客户
 
举例:
对一 实体类设计:对一关系下,类中只要包含单个对方对象类型属性即可!
public class Customer {
  private Integer customerId;
  private String customerName;
}
public class Order {
  private Integer orderId;
  private String orderName;
  private Customer customer;// 体现的是对一的关系
}  
 
对多 实体类设计:对多关系下,类中只要包含对方类型集合属性即可!
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;// 体现的是对一的关系
  
}
 
多表结果实体类设计小技巧:
- 对一,属性中包含对方对象
 - 对多,属性中包含对方对象集合
 - 只有真实发生多表查询时,才需要设计和修改实体类,否则不提前设计和修改实体类!
 - 无论多少张表联查,实体类设计都是两两考虑!
 - 在查询映射的时候,只需要关注本次查询相关的属性!例如:查询订单和对应的客户,就不要关注客户中的订单集合!
 
实际开发时,一般在开发过程中,不给数据库表设置外键约束。
原因是避免调试不方便。
一般是功能开发完成,再加外键约束检查是否有bug。
案例准备:
CREATE TABLE `t_customer` (`customer_id` INT NOT NULL AUTO_INCREMENT, `customer_name` CHAR(100), PRIMARY KEY (`customer_id`) );
CREATE TABLE `t_order` ( `order_id` INT NOT NULL AUTO_INCREMENT, `order_name` CHAR(100), `customer_id` INT, PRIMARY KEY (`order_id`) ); 
INSERT INTO `t_customer` (`customer_name`) VALUES ('c01');
INSERT INTO `t_order` (`order_name`, `customer_id`) VALUES ('o1', '1');
INSERT INTO `t_order` (`order_name`, `customer_id`) VALUES ('o2', '1');
INSERT INTO `t_order` (`order_name`, `customer_id`) VALUES ('o3', '1'); 
 
t_customer 表 与 t_order 表
 
二、对一映射
- pojo
 
@Data
public class Order {
    private int orderId;
    private String orderName;
    private int customerId;
//    一个订单对应一个客户
    private Customer customer;
}
 
- 接口
 
public interface OrderMapper {
    /**
     * 根据ID查询订单和对应客户
     * @param id
     * @return
     */
    Order queryOrderById(Integer id);
}
 
- xml
 
<mapper namespace="com.wake.mapper.OrderMapper">
    <!--  自定义映射关系,定义嵌套对象的映射关系  -->
    <resultMap id="orderMap" type="order">
        <!-- 第一层属性 order对象-->
        <!-- order的主键 id标签  -->
        <id column="order_id" property="orderId"/>
        <!-- 普通列 -->
        <result column="order_name" property="orderName"/>
        <result column="customer_id" property="customerId"/>
<!--
        对象属性赋值:
        property="customer"     order 实体类内的属性名字
        javaType="customer"     对象类型
-->
        <association property="customer" javaType="customer">
            <id column="customer_id" property="customerId"/>
            <result column="customer_name" property="customerName"/>
        </association>
    </resultMap>
        <!-- Order queryOrderById(Integer id);
                根据ID查询订单和对应客户
            -->
    <select id="queryOrderById" resultMap="orderMap">
        select order_id,order_name,tor.customer_id,customer_name
        from t_order tor
        JOIN t_customer tus
        ON tor.customer_id = tus.customer_id
        WHERE order_id = #{id};
    </select>
</mapper>
 
- 测试:
 
public class MybatisTest {
    private SqlSession sqlSession;
    @BeforeEach
    public void init() throws IOException {
        sqlSession = new SqlSessionFactoryBuilder()
                .build(Resources.getResourceAsStream("Mybatis-config.xml"))
                .openSession();
    }
    @Test
    public void testToOne(){
    //    查询订单和对应客户
        OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);
        Order order = orderMapper.queryOrderById(2);
        System.out.println(order);
        System.out.println(order.getCustomer());
    }
    @AfterEach
    public void clean(){
        sqlSession.close();
    }
}
 

三、对多映射
- pojo
 
@Data
public class Customer {
    private int customerId;
    private String customerName;
    // 一个客户 多个订单
    private List<Order> orderList;
}
 
- mapper 接口
 
public interface CustomerMapper {
    /**
     * 查询所有客户订单
     * @return
     */
    List<Customer> queryList();
}
 
- xml
 
<mapper namespace="com.wake.mapper.CustomerMapper">
    <resultMap id="customerMap" type="customer">
        <id column="customer_id" property="customerId"/>
        <result column="customer_name" property="customerName"/>
        <collection property="orderList" ofType="order">
            <id column="order_id" property="orderId"/>
            <result column="order_name" property="orderName"/>
            <result column="customer_id" property="customerId"/>
        </collection>
    </resultMap>
    <select id="queryList" resultMap="customerMap">
        select *
        from t_order tor
        JOIN t_customer tur
        ON tor.customer_id = tur.customer_id;
    </select>
</mapper>
 
- 测试
 
    @Test
    public void testToMulti(){
        // 根据客户ID 查询所有订单
        CustomerMapper customerMapper = sqlSession.getMapper(CustomerMapper.class);
        List<Customer> customers = customerMapper.queryList();
        System.out.println(customers);
        for (Customer customer : customers) {
            System.out.println(customer.getOrderList());
        }
    }
 

四、多表映射总结
4.1 多表映射优化
mybatis-config.xml 全局设置 setting
| setting属性 | 属性含义 | 可选值 | 默认值 | 
|---|---|---|---|
| autoMappingBehavior | 指定 MyBatis 应如何自动映射列到字段或属性。 NONE 表示关闭自动映射;PARTIAL 只会自动映射没有定义嵌套结果映射的字段。 FULL 会自动映射任何复杂的结果集(无论是否嵌套)。 | NONE, PARTIAL, FULL | PARTIAL | 
<!--开启resultMap自动映射-->
<setting name="autoMappingBehavior" value="FULL"/>
 
只用写 id部分 <collection
    <resultMap id="customerMap" type="customer">
        <id column="customer_id" property="customerId"/>
<!--        <result column="customer_name" property="customerName"/>-->
        <collection property="orderList" ofType="order">
            <id column="order_id" property="orderId"/>
<!--            <result column="order_name" property="orderName"/>-->
<!--            <result column="customer_id" property="customerId"/>-->
        </collection>
    </resultMap>
 
4.2 多表映射总结
| 关联关系 | 配置项关键词 | 所在配置文件和具体位置 | 
|---|---|---|
| 对一 | association标签/javaType属性/property属性 | Mapper配置文件中的resultMap标签内 | 
| 对多 | collection标签/ofType属性/property属性 | Mapper配置文件中的resultMap标签内 | 



















