7_动态SQL

  • 1_if标签

    • 接口

      public interface EmpMapper2 {
        List<Emp> findByCondition(Emp emp);
      }
      
    • 映射文件

      <?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">
      <mapper namespace="com.msb.mapper.EmpMapper2">
      
      <!--List<Emp> findByCondition(Emp emp);-->
        <select id="findByCondition" resultType="emp">
          select * from emp where 1 = 1
          <if test="empno != null">
            and empno = #{empno}
          </if>
          <if test="ename != null and ename != ''">
            and ename like concat('%',#{ename},'%')
          </if>
          <if test="job != null and job != ''">
            and job = #{job}
          </if>
          <if test="mgr != null">
            and mgr = #{mgr}
          </if>
          <if test="hiredate != null">
            and hiredate = #{hiredate}
          </if>
          <if test="sal != null">
            and sal = #{sal}
          </if>
          <if test="comm != null">
            and comm = #{comm}
          </if>
          <if test="deptno != null">
            and deptno = #{deptno}
          </if>
        </select>
      </mapper>
      
    • 测试代码

      public static void main(String[] args) {
        SqlSession sqlSession = MyBatisUtil.getSqlSession(false);
        EmpMapper2 mapper = sqlSession.getMapper(EmpMapper2.class);
        Emp condition = new Emp();
        /* condition.setDeptno(20); */
        /* condition.setSal(3000.0);  */
        /* condition.setHiredate(new java.sql.Date(81,1,22));  */
        condition.setComm(0.0);
        condition.setDeptno(20);
        List<Emp> emps = mapper.findEmpByCondition(condition);
        for (Emp e:emps) {
          System.out.println(e);
        }
      
  • 2_where标签

    • 用于处理 where 关键字和 and

      <select id="findEmpByCondition" resultType="emp">
        select * from emp
        <where>
          <if test="empno != null">
            and empno = #{empno}
          </if>
          <if test="ename != null and ename != ''">
            and ename = #{ename}
          </if>
          <if test="job != null and job != ''">
            and job = #{job}
          </if>
          <if test="mgr != null ">
            and mgr = #{mgr}
          </if>
          <if test="hiredate != null ">
            and hiredate = #{hiredate}
          </if>
          <if test="sal != null">
            and sal= #{sal}
          </if>
          <if test="comm != null ">
            and comm = #{comm}
          </if>
          <if test="deptno != null ">
            and deptno = #{deptno}
          </if>
        </where>
      </select>
      
  • 3_choose标签

    • 前面的 when 条件成立 后面的 when 就不再判断了

      <select id="findEmpByCondition2" resultType="emp">
        select * from emp
        <where>
          <choose>
            <when test="empno != null">
              and empno = #{empno}
            </when>
            <when test="ename != null and ename != ''">
              and ename = #{ename}
            </when>
            <when test="job != null and job != ''">
              and job = #{job}
            </when>
            <when test="mgr != null ">
              and mgr = #{mgr}
            </when>
            <when test="hiredate != null ">
              and hiredate = #{hiredate}
            </when>
            <when test="sal != null">
              and sal = #{sal}
            </when>
            <when test="comm != null ">
              and comm = #{comm}
            </when>
            <when test="deptno != null ">
              and deptno = #{deptno}
            </when>
          </choose>
        </where>
      </selec>
      
  • 4_set标签

    • 接口

      int updateEmpByCondition(Emp emp);
      
    • 映射文件

      <!--int updateEmpByCondtion(Emp emp);-->
      <update id="updateEmpByCondtion" >
        update emp
        <set>
          <if test="ename != null and ename != '' ">
            , ename = #{ename}
          </if>
          <if test="job != null and ename != '' ">
            , job = #{job}
          </if>
          <if test="mgr != null ">
            , mgr = #{mgr}
          </if>
          <if test="hiredate != null ">
            , hiredate = #{hiredate}
          </if>
          <if test="sal != null ">
            , sal = #{sal}
          </if>
          <if test="comm != null ">
            , comm = #{comm}
          </if>
          <if test="deptno != null ">
            , deptno = #{deptno}
          </if>
        </set>
        where empno = #{empno}
      </update>
      
  • 5_trim标签

    • Trim 标签处理 set

      <update id="updateEmpByCondition2" >
        update emp
        <!--  prefix 要增加什么前缀
        prefixOverrides 要去除什么前缀
        suffix 要增加什么后缀
        suffixOverrides 要去除什么后缀
        set 是trim的一种特殊情况
        -->
        <trim prefix="set" suffixOverrides="," >
          <if test="ename != null and ename != ''">
            ename = #{ename},
          </if>
          <if test="job != null and job != ''">
            job = #{job},
          </if>
          <if test="mgr != null ">
            mgr = #{mgr},
          </if>
          <if test="hiredate != null ">
            hiredate = #{hiredate},
          </if>
          <if test="sal != null">
            sal = #{sal},
          </if>
          <if test="comm != null ">
            comm = #{comm},
          </if>
          <if test="deptno != null ">
            deptno = #{deptno},
          </if>
        </trim>
        where empno = #{empno}
      </update>
      
    • Trim 标签 处理 where

      <select id="findEmpByCondition" resultType="emp">
      <!--  
      prefix 要增加什么前缀
      prefixOverrides 要去除什么前缀
      suffix 要增加什么后缀
      suffixOverrides 要去除什么后缀
      set 是trim的一种特殊情况
      -->
        select * from emp
          <trim prefix="where" prefixOverrides="and">
            <if test="empno != null">
              and empno = #{empno}
            </if>
            <if test="ename != null and ename != ''">
              and ename = #{ename}
            </if>
            <if test="job != null and job != ''">
              and job = #{job}
            </if>
            <if test="mgr != null ">
              and mgr = #{mgr}
            </if>
            <if test="hiredate != null ">
              and hiredate = #{hiredate}
            </if>
            <if test="sal != null">
              and sal = #{sal}
            </if>
            <if test="comm != null ">
              and comm = #{comm}
            </if>
            <if test="deptno != null ">
              and deptno = #{deptno}
            </if>
          </trim>
      </select>
      
  • 6_bind标签

    • 一般用于处理模糊查询的模板

      • 接口
        List<Emp> findEmpByEname(@Param("a") String name);
        
      • SQL语句
        <select id="findEmpByEname" resultType="  emp">
          <bind name="likePattern" value="'%'+param1+'%'"></bind>
          select * from emp where ename like #{likePattern}
        </select>
        
  • 7_sql标签

    • 代码展示

      <sql id="empColumn">empno,ename,job,mgr,hiredate,sal,comm,deptno</sql>
      <sql id="baseSelect">select <include refid="empColumn"></include> from emp</sql>
      
      <!--List<Emp> findByCondition(Emp emp);-->
      <select id="findByCondition" resultType="emp">
        <include refid="baseSelect"></include>
        <trim prefix="where" prefixOverrides="and">
          <if test="empno != null">
            and empno = #{empno}
          </if>
          <if test="ename != null and ename != ''">
            <bind name="likePattern" value="'%'+ename+'%'"/>
            and ename like #{likePattern}
          </if>
          <if test="job != null and job != ''">
            and job = #{job}
          </if>
          <if test="mgr != null">
            and mgr = #{mgr}
          </if>
          <if test="hiredate != null">
            and hiredate = #{hiredate}
          </if>
          <if test="sal != null">
            and sal = #{sal}
          </if>
          <if test="comm != null">
            and comm = #{comm}
          </if>
          <if test="deptno != null">
            and deptno = #{deptno}
          </if>
        </trim>
      </select>
      
  • 8_foreach标签

    • 代码展示

      <!--
      List<Emp> findByEmpnos1(int[] empnos);
      collection=""  遍历的集合或者是数组
                    参数是数组,collection中名字指定为array
                    参数是List集合,collection中名字指定为list
      separator=""   多个元素取出的时候 用什么文字分隔       
      open=""        以什么开头
      close=""       以什么结尾
      item=""        中间变量名
      for(Person per:PersonList)
      -->
      <select id="findByEmpnos1" resultType="emp">
        select * from emp where empno in
        <foreach collection="array" separator="," open="(" close=")" item="deptno">
          #{deptno}
        </foreach>
      </select>
      
      <!-- List<Emp> findByEmpnos2(List<Integer> empnos);-->
      <select id="findByEmpnos2" resultType="emp">
        select * from emp  where empno in
        <foreach collection="list" separator="," open="(" close=")" item="deptno">
          #{deptno}
        </foreach>
      </select>
      

8_MyBatis实现多表查询

  • 1_关联查询

    • 1_手动处理映射关系

      • 实体类
        public class Emp implements Serializable {
          private Integer empno;    
          private String name;    
          private String job;    
          private Integer mgr;    
          private Date hiredate;    
          private Double sal;    
          private Double comm;    
          private Integer deptno;
        
      • 映射文件
        <mapper namespace="com.xxx.mapper.EmpMapper">
          <!-- 
          手动处理数据库查询字段和封装实体类属性之间的映射关系
          1 主键一般使用id属性
          2 当属性名和查询出的数据表字段名相同 可以不写映射关系
          -->
          <resultMap id="empMap" type="emp">
            <!--<id property="empno" column="empno"></id>-->
            <result property="name" column="ename"></result>
            <!--
            <result property="job" column="job"></result>
            <result property="sal" column="sal"></result>
            <result property="hiredate" column="hiredate"></result>
            <result property="mgr" column="mgr"></result>
            <result property="comm" column="comm"></result>
            <result property="deptno" column="deptno"></result>
            -->
          </resultMap>
          <select id="findByEmpno" resultMap="empMap" >
            select * from emp where empno = #{empno}
          </select>
        </mapper>
        
    • 2_一对一关联查询

      • 数据准备: 创建项目表和项目记录表

        在这里插入图片描述

        CREATE TABLE `projects`  (
          `pid` int(2) NOT NULL AUTO_INCREMENT,
          `pname` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
          `money` int(11) NULL DEFAULT NULL,
          PRIMARY KEY (`pid`) USING BTREE
        ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
        
        INSERT INTO `projects` VALUES (1, ' ***大学OA', 500000);
        INSERT INTO `projects` VALUES (2, '学生选课系统', 100000);
        INSERT INTO `projects` VALUES (3, '讲师测评系统', 20000);
        INSERT INTO `projects` VALUES (4, '线上问答系统 ', 20000);
        
        CREATE TABLE `projectrecord`  (
          `empno` int(4) NOT NULL,
          `pid` int(2) NOT NULL,
          PRIMARY KEY (`empno`, `pid`) USING BTREE,
          INDEX `fk_project_pro`(`pid`) USING BTREE,
          CONSTRAINT `fk_emp_pro` FOREIGN KEY (`empno`) REFERENCES `emp` (`EMPNO`) ON DELETE CASCADE ON UPDATE CASCADE,
          CONSTRAINT `fk_project_pro` FOREIGN KEY (`pid`) REFERENCES `projects` (`pid`) ON DELETE CASCADE ON UPDATE CASCADE
        ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
        
        INSERT INTO `projectrecord` VALUES (7369, 1);
        INSERT INTO `projectrecord` VALUES (7521, 1);
        INSERT INTO `projectrecord` VALUES (7369, 2);
        INSERT INTO `projectrecord` VALUES (7499, 2);
        INSERT INTO `projectrecord` VALUES (7521, 2);
        INSERT INTO `projectrecord` VALUES (7369, 3);
        INSERT INTO `projectrecord` VALUES (7499, 3);
        INSERT INTO `projectrecord` VALUES (7521, 3);
        INSERT INTO `projectrecord` VALUES (7369, 4);
        INSERT INTO `projectrecord` VALUES (7499, 4);
        
      • 需求: 根据编号查询员工信息及所在的部门信息
        • 实体类添加一个部门作为属性
        • 实体类
        @AllArgsConstructor
        @NoArgsConstructor
        @Data
        
        public class Emp implements Serializable {
          private Integer empno;    
          private String ename;    
          private String job;    
          private Integer mgr;    
          private Date hiredate;    
          private Double sal;    
          private Double comm;    
          private Integer deptno;
        
          // 组合一个Dept对象作为自己的属性
          private Dept dept;
        }
        
        • 接口
        public interface EmpMapper {
          /**
           * 根据员工编号查询员工的所有信息并携带所在的部门信息
           * @param empno 要查询的员工编号
           * @return Emp对象, 组合了Dept对象作为属性, 对部门信息进行存储
           */
          Emp findEmpJoinDeptByEmpno(int empno);
        }
        
        • 映射文件
        <?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">
        <mapper namespace="com.msb.mapper.EmpMapper">
          <!--Emp findEmpJoinDeptByEmpno(int empno);-->
          <resultMap id="empJoinDept" type="emp">
            <!--设置emp本身的八个属性的映射关系-->
            <id property="empno" column="empno"></id>
            <result property="ename" column="ename"></result>
            <result property="job" column="job"></result>
            <result property="sal" column="sal"></result>
            <result property="hiredate" column="hiredate"></result>
            <result property="mgr" column="mgr"></result>
            <result property="comm" column="comm"></result>
            <result property="deptno" column="deptno"></result>
            <!--
            association 处理一对一
            封装一对一信息关系的标签
            property  emp类的属性名
            javaType  用哪个类的对象给属性赋值
            -->
        
            <association property="dept" javaType="dept">
              <id column="deptno" property="deptno"></id>
              <result column="dname" property="dname"></result>
              <result column="loc" property="loc"></result>
            </association>
          </resultMap>
        
          <select id="findEmpJoinDeptByEmpno" resultMap="empJoinDept" >
            select * from
            emp e
            left join dept d
            on e.deptno = d.deptno
            where empno = #{empno}
          </select>
        </mapper>
        
      • 测试代码
        @Test
        public void testOneToOne() throws ParseException {
          EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
          Emp emp = mapper.findEmpJoinDeptByEmpno(7499);
          System.out.println(emp);
        }
        
    • 3_一对多关联查询

      • 根据部门号查询部门信息及该部门的所有员工信息
      • 实体类
        @Data
        @AllArgsConstructor
        @NoArgsConstructor
        public class Dept implements Serializable {
          private Integer deptno;    
          private String dname;    
          private String loc;
          
          // 组合一个Emp的List集合作为属性
          private List<Emp> empList;
        }
        
      • 接口
        package com.xxx.mapper;
        
        import com.xxx.pojo.Dept;
        
        public interface DeptMapper {
          /**
           * 根据部门编号查询部门信息及该部分的所有员工信息
           * @param deptno 要查询的部门编号
           * @return Dept对象, 内部组合了一个Emp的List属性用于封装部门的所有员工信息
           */
          Dept findDeptJoinEmpsByDeptno(int deptno);
        }
        
      • 映射文件
        <?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">
        
        <mapper namespace="com.xxx.mapper.DeptMapper">
          <!--Dept findDeptJoinEmpsByDeptno(int deptno);-->
          <resultMap id="deptJoinEmps" type="dept">
            <id column="deptno" property="deptno"></id>
            <result column="dname" property="dname"></result>
            <result column="loc" property="loc"></result>
            <!--处理一对多关系的标签-->
            <collection property="empList" ofType="emp" >
              <!--设置emp本身的八个属性的映射关系-->
              <id property="empno" column="empno"></id>
              <result property="ename" column="ename"></result>
              <result property="job" column="job"></result>
              <result property="sal" column="sal"></result>
              <result property="hiredate" column="hiredate"></result>
              <result property="mgr" column="mgr"></result>
              <result property="comm" column="comm"></result>
              <result property="deptno" column="deptno"></result>
            </collection>
          </resultMap>
        
          <select id="findDeptJoinEmpsByDeptno" resultMap="deptJoinEmps">
            select * from dept d left join emp e on d.deptno =e.deptno where d.deptno =#{deptno}
          </select>
        </mapper>
        
      • 测试代码
        @Test
        public void testOneToMany() throws ParseException {
          DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
          Dept dept = mapper.findDeptJoinEmpsByDeptno(20);
          System.out.println(dept);
          System.out.println("---------");
          List<Emp> empList = dept.getEmpList();
          empList.forEach(System.out::println);
        }
        
    • 4_多对多关联查询

      • 根据项目编号查询项目信息, 以及参与到该项目之中的所有的员工信息
      • 实体类
        @NoArgsConstructor
        @AllArgsConstructor
        @Data
        public class Project implements Serializable {
          private Integer pid;
          private String pname;
          private Integer money;
        
          // 组合一个ProjectRecord对象集合作为属性
          private List<ProjectRecord> projectRecords;
        }
        
        @Data
        @AllArgsConstructor
        @NoArgsConstructor
        
        public class ProjectRecord implements Serializable {
          private Integer empno;    
          private Integer pid;
        
          // 组合一个Emp对象作为属性
          private Emp emp;
        }
        
      • 接口
        package com.xxx.mapper;
        
        import com.xxx.pojo.Emp;
        import com.xxx.pojo.Project;
        
        public interface ProjectMapper {
          /**     
           * 根据项目编号查询一个项目信息及参与该项目的所有员工信息     
           * @param pid 项目编号     
           * @return 所有信息封装的Project对象     
           */
          Project findProjectJoinEmpsByPid(int pid);
        }
        
      • 映射文件
        <?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">
        
        <mapper namespace="com.msb.mapper.ProjectMapper">
          <!--Project findProjectJoinEmpsByPid(int pid);-->
          <resultMap id="projectJoinEmps" type="project">
            <id column="pid" property="pid"></id>
            <result column="pname" property="pname"></result>
            <result column="money" property="money"></result>
            <!--一对多 集合属性 collection-->
            <collection property="projectRecords" ofType="projectRecord">
              <id column="empno" property="empno"></id>
              <id column="pid" property="pid"></id>
              <!--一对一 -->
              <association property="emp" javaType="emp">
                <id property="empno" column="empno"></id>
                <result property="ename" column="ename"></result>
                <result property="job" column="job"></result>
                <result property="sal" column="sal"></result>
                <result property="hiredate" column="hiredate"></result>
                <result property="mgr" column="mgr"></result>
                <result property="comm" column="comm"></result>
                <result property="deptno" column="deptno"></result>
              </association>
            </collection>
          </resultMap>
        
          <select id="findProjectJoinEmpsByPid"  resultMap="projectJoinEmps">
            select * from
            project p
            left join projectrecord pr
            on p.pid = pr.pid
            left join emp e
            on e.empno = pr.empno
            where p.pid= #{pid}
          </select>
        </mapper>
        
      • 测试代码
        @Test
        public void testManyToMany() throws ParseException {
          ProjectMapper mapper = sqlSession.getMapper(ProjectMapper.class);
          Project project = mapper.findProjectJoinEmpsByPid(2);
          System.out.println(project.getPid());
          System.out.println(project.getPname());
          System.out.println(project.getMoney());
        
          List<ProjectRecord> projectRecords = project.getProjectRecords();
          for (ProjectRecord projectRecord : projectRecords) {
            Emp emp = projectRecord.getEmp();
            System.out.println(emp);
          }
        }
        
  • 2_级联查询

    • 概念

      • 级联查询,顾名思义,就是利于数据库表间的外键关联关系进行自动的级联查询操作
      • 使用 MyBatis 实现级联查询,除了实体类增加关联属性外,还需要在映射文件中进行配置
    • 1_立即加载

      • 功能1:查询所有员工的信息(多对一关联)
        • 经过对比,发现经过在映射文件中配置,测试类的代码大大简化了,无需手动进行关联查询和组装数据了
      • 功能2:查询10号部门及其该部门员工信息
        • Dept 和 Emp实体类
        @Data
        @AllArgsConstructor
        @NoArgsConstructor
        
        public class Dept implements Serializable {
          private Integer deptno;
          private String dname;
          private String loc;
        
          // 当前部门下的所有员工对象的List集合
          private List<Emp> empList;
        }
        
        @Data
        @AllArgsConstructor
        @NoArgsConstructor
        public class Emp implements Serializable {
          private Integer empno;    
          private String ename;    
          private String job;    
          private Integer mgr;    
          private Date hiredate;    
          private Double sal;    
          private Double comm;    
          private Integer deptno;
        }
        
        • DeptMapper 和 EmpMapper 接口
        package com.xxx.mapper;
        
        import com.xxx.pojo.Dept;
        
        public interface DeptMapper {
          Dept findDeptByDeptno(int deptno);
        }
        
        package com.xxx.mapper;
        
        import com.xxx.pojo.Emp;
        import java.util.List;
        
        public interface EmpMapper {
          List<Emp> findEmpsByDeptno(int deptno);
        }
        
    • 2_延迟加载 (按需加载)

      • 概念
        • 延迟加载的内容等到真正使用时才去进行加载(查询),多用在关联对象或集合中
      • 好处
        • 先从单表查询、需要时再从关联表去关联查询,大大降低数据库在单位时间内的查询工作量,将工作在时间上的分配更加均匀,而且单表要比关联查询多张表速度要快
      • 延迟加载的设置
        • 第一步:全局开关 --> 在 sqlMapConfig.xml 中打开延迟加载的开关
          • 配置完成后所有的 association 和 collection 元素都生效
          <settings>
            <setting name="lazyLoadingEnabled" value="true"/>
            <setting name="aggressiveLazyLoading" value="true"/>
          </settings>
          
          • lazyLoadingEnabled
            • 是否开启延迟加载
            • 是 Mybatis 是否启用懒加载的全局开关
            • 当开启时,所有关联对象都会延迟加载
            • 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态
          • aggressiveLazyLoading
            • 当开启时,任何方法的调用都会懒加载对象的所有属性
            • 否则,每个属性会按需加载
        • 第二步:分开关 --> 指定的 association 和 collection 元素中配置 fetchType 属性
          • eager:表示立刻加载
          • lazy:表示延迟加载
            • 将覆盖全局延迟设置
  • 3_总结

    • resultMap中的常见属性

      属性 描述
      property 需要映射到 JavaBean 的属性名称
      javaType property 的类型,一个完整的类名,或者是一个类型别名。如果你匹配的是一个JavaBean,那 MyBatis 通常会自行检测到
      column 数据表的列名或者列别名
      jdbcType column 在数据库表中的类型。这个属性只在 insert、update 或 delete 的时候针对允许空的列有用。JDBC 需要这项,但 MyBatis 不需要
      typeHandler 使用这个属性可以覆写类型处理器,实现 javaType、jdbcType 之间的相互转换。一般可以省略,会探测到使用的什么类型的 typeHandler 进行处理
      fetchType 自动延迟加载
      select association、collection的属性,使用哪个查询属性的值,要求指定namespace+id的全名称
      ofType collection的属性,指明集合中元素的类型(即泛型类型)
    • 级联查询和多表查询的比较及其选择

      对比项 级联查询 多表查询
      SQL语句数 多条 一条
      性能 性能低 性能高
      延迟加载 立即加载、延迟加载 只有立即加载
      灵活性 更灵活 不灵活
      SQL难易度 简单 复杂
      选择依据 简单、灵活 高性能
    • ResultType 和 ResultMap 使用场景

      • 1) 如果你做的是单表的查询并且封装的实体和数据库的字段 一一 对应 resultType
      • 2) 如果实体封装的属性和数据库的字段不一致 resultMap
      • 3) 使用 N+1 级联查询的时候 resultMap
      • 4) 使用的是多表的连接查询 resultMap
    • 一对一关联映射的实现

      • 1) 实例:学生和学生证、雇员和工牌
      • 2) 数据库层次:主键关联或者外键关联(参看之前内容)
      • 3) MyBatis层次:在映射文件的设置双方均使用 association 即可,用法相同
    • 多对多映射的实现

      • 1) 实例:学生和课程、用户和角色
      • 2) 数据库层次:引入一个中间表将一个多对多转为两个一对多
      • 3) MyBatis层次
        • 方法1:在映射文件的设置双方均使用 collection 即可,不用引入中间类
        • 方法2:引入中间类和中间类的映射文件,按照两个一对多处理
    • 自关联映射

      • 1) 实例:Emp表中的员工和上级。一般是一对多关联
      • 2) 数据库层次:外键参考当前表的主键(比如 mgr 参考 empno)
      • 3) MyBatis层次:按照一对多处理,但是增加的属性都写到一个实体类中,增加的映射也都写到一个映射文件中

9_MyBatis注解开发

  • 代码展示

    public interface DeptMapper {
      Dept findDeptByDeptno(int deptno);
      @Select("select * from dept where deptno =#{deptno}")
      Dept findByDeptno(int deptno);
      @Update("update dept set dname =#{dname}, loc =#{loc} where deptno =#{deptno}")
      int updateDept(Dept dept);
      @Insert("insert into dept values(DEFAULT,#{dname},#{loc})")
      int addDept(Dept dept);
      @Delete("delete from dept where deptno =#{deptno}")
      int removeDept(int deptno);
    }
    
    • 1.使用注解没有实现Java代码和SQL语句的解耦

    • 2.无法实现SQL语句的动态拼接

    • 3.进行多表的查询时定制 ResultMap 比较麻烦

  • 注解和XML的优缺点

    维度 XML 注解 (Annotation)
    优点 1 类和类之间的解耦 简化配置
    优点 2 利于修改。直接修改 XML 文件,无需到源代码中修改。 使用起来直观且容易,提升开发效率
    优点 3 配置集中在 XML 中,对象间关系一目了然,利于快速了解项目和维护 类型安全,编译器进行校验,不用等到运行期才会发现错误。
    优点 4 容易和其他系统进行数据交换 注解的解析可以不依赖于第三方库,可以直接使用 Java 自带的反射

更多推荐