一文带你快速搭建框架(三)

160 阅读6分钟

本文正在参加「金石计划 . 瓜分6万现金大奖」

5.处理表字段和实体类属性名不一致的情况

  • 方式一:给字段名取别名

    • 如果表中字段名和实体类属性名不一致,可以在SQL语句中给字段名取别名
    • 给字段取得别名必须和实体类属性名一致
  • 方式二:在核心配置文件中配置驼峰映射

    • 使用前提:表字段符合Mysql命名规范(使用下划线_分割单词),而实体类属性符合驼峰命名规范

    • 使用方式:

      1. 在核心配置文件中使用 标签,在该标签下使用 子标签来配置
      2. 给子标签 设置name属性值为mapUnderscoreToCamelCase,value属性值为true
    • 范例

      <settings>
          <setting name="mapUnderscoreToCamelCase" value="true" />
      </settings>
      
    • 在核心配置文件使用了如上配置后,在SQL语句中可以使用表的字段名而不用考虑表字段名和实体类属性名不一致的情况

  • 方式三:在映射配置文件中使用标签自定义映射

    • 标签含有id属性和type属性,其中id属性是设置当前自定义映射的标识,type属性是映射的实体类

    • 标签下含有的子标签以及功能

      1. 标签:设置主键字段的映射关系,使用column属性设置映射关系中表的字段名,使用property属性设置映射关系中实体类的属性名
      2. 标签:设置普通字段的映射关系,使用column属性设置映射关系中表的字段名,使用property属性设置映射关系中实体类的属性名
    • 范例

      <resultMap id="empResultMap" type="Emp">
          <id column="emp_id" property="empId"></id>
          <result column="emp_name" property="empName"></result>
          <result column="age" property="age"></result>
          <result column="gender" property="gender"></result>
      </resultMap><select id="getEmpByEmpId" resultType="Emp" resultMap="empResultMap">
          select * from t_emp where emp_id = #{empId}
      </select>
      
    • 注意:SQL语句所在标签中的resultMap属性值必须是自定义映射的id

6.多对一映射关系的处理

  • 这里多对一是指实体类中某个属性是以表中多个字段为属性构成的实体类,如员工类的部门属性,部门属性的类型是部门类,这个部门类有部门id,部门名称

  • 方式一:使用级联

    • 配置

      <resultMap id="getEmpAndDeptByEmpIdResultMap" type="Emp">
          <id column="emp_id" property="empId"></id>
          <result column="emp_name" property="empName"></result>
          <result column="age" property="age"></result>
          <result column="gender" property="gender"></result>
          <result column="dept_id" property="dept.deptId"></result>
          <result column="dept_name" property="dept.deptName"></result>
      </resultMap><select id="getEmpAndDeptByEmpId" resultMap="getEmpAndDeptByEmpIdResultMap">
            select emp_id,emp_name,age,gender,t_dept.dept_id,dept_name
            from t_emp left join t_dept
            on t_emp.dept_id = t_dept.dept_id where emp_id = #{empId}
      </select>
      
  • 方式二:使用标签

    • 配置

      <resultMap id="getEmpAndDeptByEmpIdResultMap" type="Emp">
          <id column="emp_id" property="empId"></id>
          <result column="emp_name" property="empName"></result>
          <result column="age" property="age"></result>
          <result column="gender" property="gender"></result>
          <association property="dept" javaType="Dept">
              <id column="dept_id" property="deptId"></id>
              <result column="dept_name" property="deptName"></result>
          </association>
      </resultMap>
      ​
      <select id="getEmpAndDeptByEmpId" resultMap="getEmpAndDeptByEmpIdResultMap">
            select emp_id,emp_name,age,gender,t_dept.dept_id,dept_name
          from t_emp left join t_dept
            on t_emp.dept_id = t_dept.dept_id where emp_id = #{empId}
      </select>
      

    注意:association标签中property属性是指映射实体类中属性的名称,javaType是它的类型,而association标签下的id标签和result标签中的property属性是指javaType指定的类中的属性名称,column属性指表中的字段名

  • 方式三:使用分步查询

    • 配置

      查询员工信息:

      <resultMap id="getEmpAndDeptByEmpIdResultMap" type="Emp">
          <id column="emp_id" property="empId"></id>
          <result column="emp_name" property="empName"></result>
          <result column="age" property="age"></result>
          <result column="gender" property="gender"></result>
          <association 
                       property="dept"
                       select="com.liaoxiangqian.mapper.DeptMapper.getDeptByDeptId"
                       column="dept_id">
          </association>
      </resultMap>
      ​
      <select id="getEmpAndDeptByEmpId" resultMap="getEmpAndDeptByEmpIdResultMap">
          select * from t_emp where emp_id = #{empId}
      </select>
      

      根据员工的部门id查询部门信息

      <resultMap id="getDeptByDeptIdResultMap" type="Dept">
          <id column="dept_id" property="deptId"></id>
          <result column="dept_name" property="deptName"></result>
      </resultMap>
      ​
      <select id="getDeptByDeptId" resultMap="getDeptByDeptIdResultMap">
          select * from t_dept where dept_id = #{deptId}
      </select>
      

7.一对多映射关系的处理

-   **这里一对多是指实体类中某个属性是由许多实体类构成的集合**,如部门类中员工属性是一个List集合
  • 方式一:使用标签

    • 配置

      <resultMap id="getDeptAndEmpByDeptIdResultMap" type="Dept">
          <id column="dept_id" property="deptId"></id>
          <result column="dept_name" property="deptName"></result>
          <collection property="emps" ofType="Emp">
              <id column="emp_id" property="empId"></id>
              <result column="emp_name" property="empName"></result>
              <result column="age" property="age"></result>
              <result column="gender" property="gender"></result>
          </collection>
      </resultMap>
      ​
      <select id="getDeptAndEmpByDeptId" resultMap="getDeptAndEmpByDeptIdResultMap">
          select *
          from t_dept left join t_emp
          on t_dept.dept_id = t_emp.dept_id
          where t_dept.dept_id = #{deptId}
      </select>
      
  • 方式二:使用分步查询

    • 配置

      查询部门信息

      <resultMap id="getDeptAndEmpByDeptIdResultMap" type="Dept">
          <id column="dept_id" property="deptId"></id>
          <result column="dept_name" property="deptName"></result>
          <collection property="emps" 
                      select="com.liaoxiangqian.mapper.EmpMapper.getEmpByDeptId" 
                      column="dept_id">
          </collection>
      </resultMap>
          
      <select id="getDeptAndEmpByDeptId" resultMap="getDeptAndEmpByDeptIdResultMap">
          select * from t_dept where dept_id = #{deptId}
      </select>
      

      根据部门id查询员工信息

      <resultMap id="getEmpByDeptIdResultMap" type="Emp">
          <id column="emp_id" property="empId"></id>
          <result column="emp_name" property="empName"></result>
          <result column="age" property="age"></result>
          <result column="gender" property="gender"></result>
      </resultMap><select id="getEmpByDeptId" resultMap="getEmpByDeptIdResultMap">
          select * from t_emp where dept_id = #{deptId}
      </select>
      

8.分布查询的优点

  • 分布查询的优点是可以实现延迟加载

  • 延迟加载可以避免在分步查询中执行所有的SQL语句,节省资源,实现按需加载

  • 需要在核心配置文件中添加如下的配置信息

    <settings>
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"/>
    </settings>
    
  • lazyLoadingEnabled表示全局的延迟加载开关,true表示所有关联对象都会延迟加载,false表示关闭

  • aggressiveLazyLoading表示是否加载该对象的所有属性,如果开启则任何方法的调用会加载这个对象的所有属性,如果关闭则是按需加载

  • 由于这个配置是在核心配置文件中设定的,所以所有的分步查询都会实现延迟加载,而如果某个查询不需要延迟加载,可以在collection标签或者association标签中的fetchType属性设置是否使用延迟加载,属性值lazy表示延迟加载,属性值eager表示立即加载

    9.动态SQL

  • if标签

    • if标签通过test属性给出判断的条件,如果条件成立,则将执行标签内的SQL语句

    • 范例

      <select id="getEmpByCondition" resultType="Emp">
          select * from t_emp where
          <if test="empName != null and empName != ''">
              emp_name = #{empName}
          </if>
          <if test="age != null and age != ''">
              and age = #{age}
          </if>
          <if test="gender != null and gender != ''">
              and gender = #{gender}
          </if>
      </select>
      
  • where标签

    • 考虑if标签中的范例出现的一种情况:当第一个if标签条件不成立而第二个条件成立时,拼接成的SQL语句中where后面连着的是and,会造成SQL语句语法错误,而where标签可以解决这个问题

    • 范例

      <select id="getEmpByCondition" resultType="Emp">
          select * from t_emp
          <where>
              <if test="empName != null and empName != ''">
                  emp_name = #{empName}
              </if>
              <if test="age != null and age != ''">
                  and age = #{age}
              </if>
              <if test="gender != null and gender != ''">
                  and gender = #{gender}
              </if>
          </where>
      </select>
      
    • where标签只会在子标签返回任何内容的情况下才插入WHERE子句。而且,若子句的开头有多余的and或者or,where标签也会将它们去除,但是子句末尾的and或者or不能去除

  • trim标签

    • trim标签用于去掉或添加标签中的内容

    • trim标签常用属性

      1. prefix:在trim标签中的内容的前面添加某些内容
      2. prefixOverrides:在trim标签中的内容的前面去掉某些内容
      3. suffix:在trim标签中的内容的后面添加某些内容
      4. suffixOverrides:在trim标签中的内容的后面去掉某些内容
    • 用trim实现where标签范例相同的功能

      <select id="getEmpByCondition" resultType="Emp">
          select * from t_emp
          <trim prefix="where" prefixOverrides="and">
              <if test="empName != null and empName != ''">
                  emp_name = #{empName}
              </if>
              <if test="age != null and age != ''">
                  and age = #{age}
              </if>
              <if test="gender != null and gender != ''">
                  and gender = #{gender}
              </if>
          </trim>
      </select>
      
  • choose、when、otherwise标签

    • 这三个标签是组合使用的,用于在多条件中选择一个条件,类似Java中的if...else if...else...语句

    • 范例

      <select id="getEmpByCondition" resultType="Emp">
          select * from t_emp where gender = #{gender}
          <choose>
              <when test="empName != null and empName != ''">
                  and emp_name = #{empName}
              </when>
              <when test="age != null and age != ''">
                  and age = #{age}
              </when>
          </choose>
      </select>
      
    • 当某个when标签的条件满足时将对应的SQL语句返回,如果都不满足并且有otherwise标签时,才会返回otherwise标签中的SQL语句

  • foreach标签

    • foreach标签允许指定一个集合或数组,并且对这个集合或数组进行遍历

    • foreach标签可以用的属性有

      1. collection:指定需要遍历的集合或数组
      2. item:当前遍历到的元素
      3. index:当前遍历到的元素的序号
      4. 当遍历的集合是Map类型时,index表示键,item表示值
      5. open:指定遍历开始前添加的字符串
      6. close:指定遍历开始后添加的字符串
      7. separator:指定每次遍历之间的分隔符
    • collection属性值注意事项

      • 如果遍历的是List时,属性值为list
      • 如果遍历的是数组时,属性值为array
      • 如果遍历的是Map时,属性值可以是map.keys()map.values()map.entrySet()
      • 除此之外,还可以在映射方法的参数中使用 @Param() 注解自定义collection属性值
    • 批量添加数据

      <insert id="addMoreEmp">
          insert into t_emp values
          <foreach collection="list" separator="," item="emp">
              (null,#{emp.empName},#{emp.age},#{emp.gender},null)
          </foreach>
      </insert>
      
    • 批量删除数据

      <delete id="deleteMoreEmp">
          delete from t_emp where emp_id in
          <foreach collection="array" item="empId" separator="," open="(" close=")">
              #{empId}
          </foreach>
      </delete>
      
  • sql标签

    • 用于记录一段通用的SQL语句片段,在需要用到该SQL语句片段的地方中通过include标签将该SQL语句片段插入

    • sql标签通过id属性唯一标识一个SQL语句片段,include标签通过refid属性指定使用某个SQL片段

    • 范例

      <sql id="item">
          emp_id,emp_name,age,gender,dept_id
      </sql>
      <select id="getEmpByEmpId" resultType="Emp">
          select <include refid="item"></include>
          from t_emp
          where emp_id = #{empId}
      </select>