• 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=虚竹]]]
  • 相关阅读:
    Heroku
    windows平台
    ORTP编译为静态库的问题
    关于Visual Studio 2013 编译 multi-byte character set MFC程序出现 MSB8031 错误的解决办法
    Windows API 磁盘
    Unity项目苹果提审Mach-O文件大于80M问题解决方法
    Unity加载prefab时调用脚本函数顺序和内存释放问题
    Unity3d中多足怪的物理RagDoll实现
    手游各个系统及UI架构剖析
    手游客户端数据表接入随笔
  • 原文地址:https://www.cnblogs.com/abcdjava/p/11192439.html
Copyright © 2020-2023  润新知