MyBatis的对象关系映射---一对多N+1策略★★★★★

Posted abcdjava

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MyBatis的对象关系映射---一对多N+1策略★★★★★相关的知识,希望对你有一定的参考价值。

在实际开发中,一个业务可能涉及到多个数据表的查询,那么多表查询就涉及连接查询(等值连接), 等值连接 表与表之间有一个外键关键,但是程序中最终获取的表封装的对象, 对象与对象之间是没有外键关系的,对象和对象之间只有依赖关系;

 对象之间关系主要是四种:

一对一 关系
一个人对应身份证id,一个QQ号对应一个QQ空间

一对多 关系

一个部门对应多个员工

多对一 关系

多个员工对应一个部门

多对多 关系

多个学生对应多个老师,多个学生对应多个课程

什么关系应该从哪个对象作为中心点来看

一对多, 以one方作为中心点

MyBatis框架支持多表查询封装对象之间关系

<collection> 一对多查询 <association>多对一和一对一查询

MyBatis的对象关系映射---一一对多N+1策略:

mapper表:

 

 1 package top.abcdit.mybatis.mapper;
 2 
 3 import top.abcdit.mybatis.pojo.Department;
 4 
 5 public interface One2ManyMapper 
 6     
 7     /**
 8      * 根据id查询出部门的所有信息(包括部门下面的所有员工)
 9      * @param id 部门id
10      * @return 部门对象
11      */
12     
13     Department selectByPrimaryKey(Integer id);
14     
15 

One2ManyMapper.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">

<!--  映射标签,内部就编写具体的映射sql语句
    namespace :命名空间,值 必须是 对应接口的全限定名 = 包名 +简单类名
        top.abcdit.mybatis.mapper.One2ManyMapper
 -->

<mapper namespace="top.abcdit.mybatis.mapper.One2ManyMapper">
    
    <select id="selectByPrimaryKey" parameterType="int" resultMap="dept_map">
        select * from department where id = #id
    </select>
    
    <resultMap type="top.abcdit.mybatis.pojo.Department" id="dept_map">
        <id column="id" property="id"/>
        <result column="name" property="name"/>
        
        <!-- 
              问题: private List<Employee> employees; 员工集合如何映射?
              解决方案:使用 <collection>集合标签
              <collection property="" column="" select=""/>    
              property :需要映射的属性 此时就是 employees
              column:当前部门的主键 id
              select : 需要去查询的对应员工的功能id
           -->
        
        <collection property="employees" column="id" select="selectEmployeesByDeptId"/>
        
    </resultMap>
    
    <!-- 联合查询的功能 -->
      <!-- 根据部门的id查询出所有的员工 -->
      
      <select id="selectEmployeesByDeptId" parameterType="int" resultType="top.abcdit.mybatis.pojo.Employee">
          select * from employee where dept_id = #id
      </select>
    
    
</mapper>

 

mybatis-config.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
  
  <!-- mybatis配置标签 内部就是mybatis具体配置 -->
<configuration>
    <!-- mybatis的配置环境 
        default:默认使用环境,值就是下面的环境id
    -->
    <settings>
    <!-- 开启二级缓存 -->
        <setting name="cacheEnabled" value="true"/>
    </settings>
        
  <environments default="mysql">
      <!-- 具体某一个环境 -->
    <environment id="mysql">
    <!-- MyBatis操作需要事务管理,默认使用JDBC
            JDBC:mybatis的别名
     -->
      <transactionManager type="JDBC"/>
      <!--配置mybatis的数据源(连接池)
      POOLED(别名) :mybatis内置的一个连接池
          后期和spring集成使用,druid阿里巴巴连接池
 -->
      <dataSource type="POOLED">
          <!-- 数据库驱动 -->
        <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
        <!-- url地址 -->
        <property name="url" value="jdbc:mysql://localhost:3306/gzmybatis1?useUnicode=true&amp;characterEncoding=utf-8&amp;serverTimezone=GMT"/>
        <!-- 数据库的账号 -->
        <property name="username" value="root"/>
        <!-- 数据库的密码 -->
        <property name="password" value="myroot"/>
      </dataSource>
    </environment>
  </environments>
  
  <!-- 配置映射文件 -->
  <mappers>
          <!-- 读取单个映射文件 -->
    <mapper resource="top/abcdit/mybatis/mapper/One2ManyMapper.xml"/>
  </mappers>
</configuration>

员工和部门表:

package top.abcdit.mybatis.pojo;

import java.util.List;

public class Department 
    private Integer id;
    private String name;
    
    //一个部门对应多个员工:一对多关系
    //此时我们必须有集合来描述
    private List<Employee> employees;

    public Integer getId() 
        return id;
    

    public void setId(Integer id) 
        this.id = id;
    

    public String getName() 
        return name;
    

    public void setName(String name) 
        this.name = name;
    

    public List<Employee> getEmployees() 
        return employees;
    

    public void setEmployees(List<Employee> employees) 
        this.employees = employees;
    

    @Override
    public String toString() 
        return "Department [id=" + id + ", name=" + name + ", employees=" + employees + "]";
    
    
package top.abcdit.mybatis.pojo;

public class Employee 
    
    private Integer id;
    private String name;
    public Integer getId() 
        return id;
    
    public void setId(Integer id) 
        this.id = id;
    
    public String getName() 
        return name;
    
    public void setName(String name) 
        this.name = name;
    
    @Override
    public String toString() 
        return "Employee [id=" + id + ", name=" + name + "]";
    
    

Util工具表:

package top.abcdit.mybatis.util;

import java.io.InputStream;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

public class MyBatisUtil 
    private MyBatisUtil() 
    private static SqlSessionFactory sqlSessionFactory;
    
        static 
            //读取主配置文件
            String resource = "mybatis-config.xml";
            
            //java7(jdk1.7)开始,支持在try()括号里直接自动释放资源
            try(InputStream inputStream = Resources.getResourceAsStream(resource);) 
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
             catch (Exception e) 
                e.printStackTrace();
            
        
    public static SqlSession openSession() 
        //创建sqlSession回话对象
        SqlSession sqlSession = sqlSessionFactory.openSession();
        return sqlSession;
        
    
        
    public static void main(String[] args) 
        SqlSession sqlSession = openSession();
        System.out.println(sqlSession);
        

测试表:

 1 package top.abcdit.mybatis.mapper;
 2 
 3 import static org.junit.Assert.*;
 4 
 5 import org.apache.ibatis.session.SqlSession;
 6 import org.junit.Test;
 7 
 8 import top.abcdit.mybatis.pojo.Department;
 9 import top.abcdit.mybatis.util.MyBatisUtil;
10 
11 public class One2ManyMapperTest 
12 
13     @Test
14     public void testSelectByPrimaryKey() 
15         
16         SqlSession session = MyBatisUtil.openSession();
17         One2ManyMapper mapper = session.getMapper(One2ManyMapper.class);
18         
19         Department dept = mapper.selectByPrimaryKey(2);
20         System.out.println(dept);
21         
22     
23 
24 

输出结果:

DEBUG [main] - ==>  Preparing: select * from department where id = ? 
DEBUG [main] - ==> Parameters: 2(Integer)
TRACE [main] - <==    Columns: id, name
TRACE [main] - <==        Row: 2, 研发部
DEBUG [main] - ====>  Preparing: select * from employee where dept_id = ? 
DEBUG [main] - ====> Parameters: 2(Integer)
TRACE [main] - <====    Columns: id, name, dept_id
TRACE [main] - <====        Row: 2, 虚竹, 2
DEBUG [main] - <====      Total: 1
DEBUG [main] - <==      Total: 1
Department [id=2, name=研发部, employees=[Employee [id=2, name=虚竹]]]

 

以上是关于MyBatis的对象关系映射---一对多N+1策略★★★★★的主要内容,如果未能解决你的问题,请参考以下文章

mybatis xml数据层框架应用--Mybatis关系映射之一对多关系映射

mybatis xml数据层框架应用--Mybatis关系映射之一对一关系映射

MyBatis关联映射:一对一一对多总结一二

MyBatis的关联映射

MyBatis --- 映射关系一对一对多多对多,懒加载机制

mybatis--对象关系映射细节详解