学习MyBatis必知必会(7)~注解开发、动态SQL
阅读原文时间:2022年02月05日阅读:1
  • 开发中推荐是使用xml文件配置

1、配置映射关系【使用注解的方式】:

<!-- 全局的配置文件 -->
<configuration>
   <!-- 2、关联映射文件/ 关联Mapper接口  -->
    <mappers>
        <!--  <mapper resource="com/shan/hello/mapper/UserMapper.xml"/>-->
        <mapper class="com.shan.hello.mapper.UserMapper"/>
    </mappers>
  </configuration>

2、通过注解,把sql和映射写到Mapper接口:

public interface UserMapper {

    @Insert("insert into t_user (name, salary) values (#{name}, #{salary});")
    @Options(useGeneratedKeys = true,keyProperty = "id")
    void save(User user);

    @Delete("delete from t_user where id = #{id};")
    void delete(Long id);

    @Update("update t_user set name = #{name}, salary = #{salary} where id = #{id};")
    void update(User user);
//    void update(User user, Long id);//错误:myBatis默认只能传递一个参数

    @Select("select id u_id, name as u_name, salary u_salary from t_user where id = #{id}")
    @Results(id="BaseResultMap", value= {
            @Result(column = "u_id",property = "id"),
            @Result(column = "u_name",property = "name"),
            @Result(column = "u_salary",property = "salary")
    })
    User get(Long id);

    @Select("select id u_id, name as u_name, salary u_salary from t_user")
    @ResultMap("BaseResultMap")
    List<User> getListAll();
}

3、测试(这里以测试查询为例):

    /* 测试查询 */
    @Test
    public void testGet() throws IOException {
        SqlSession session = MyBatisUtil.getSession();
        UserMapper userMapper = session.getMapper(UserMapper.class);
        User user = userMapper.get(2L);
        System.out.println(user);
        //5、关闭资源
        session.close();
    }
  • if

  • choose (when, otherwise)

  • trim (where, set)

  • foreach

  • 其他(bind,sql,include)

1、if 举例:

  <!-- 映射文件 -->
  <select id="select" resultType="Employee">
      select * from employee
      <if test="minSalary != null">
          where salary >= #{minSalary}
      </if>
  </select>
  • 细节:在xml中 小于符合不能直接输入 < , 会被当做标签的开始标志,需要使用转义符号 &lt;

  • 防止第一个查询条件是null,加上 where 1=1,然后其他查询条件接着and 写。

2、choose (when, otherwise) 举例:

 <!-- 映射文件 -->
 <select id="select" resultType="Employee">
          select * from employee where 1=1
      <if test="minSalary != null">
          and salary >= #{minSalary}
      </if>
      <choose>
          <when test="deptId > 0">and deptId = #{deptId}</when>
          <otherwise>and deptId is not null</otherwise>
      </choose>
  </select>

3-1、trim (where, set)- where 举例:

  • 解决sql拼接查询条件时第一个条件为null,而加上 where 1=1,导致不能进行索引查询,影响性能。

  • where 元素:判断查询条件是否有where关键字,若没有,则第一个查询条件之前要插入 where

    ​ 若发现查询条件是以and/or开头,则会把第一个查询条件前的and/or 替换成 where

3-2、trim (where, set)-set 举例:

  • 和where 类似,动态去掉最后一个逗号

    update Author username=#{username}, password=#{password}, email=#{email}, bio=#{bio} where id=#{id}

3-3、trim (where, set)-trim :

<trim prefix="" prefixOverrides="" suffix="" suffixOverrides="">
    <!--trim 包含的动态 SQL-->
</trim>

prefix – 在这个字符串之前插入 prefix 属性值。

prefixOverrides – 并且字符串的内容以 prefixOverrides 中的内容开头(可以包含管道符号),那么使用 prefix 属性值替换内容的开头。

suffix – 在这个字符串之后插入 suffix 属性值。

suffixOverrides –并且字符串的内容以 suffixOverrides 中的内容结尾(可以包含管道符号),那么使用 suffix 属性值替换内容的结尾。

  • 使用 where 等价于: 注意:此时 AND 后面有一个空格。

  • 使用 set 等价于:

4、foreach 举例1:

/* Mapper接口 */
void batchDelete(@Param("ids")List<Long> ids);

<!-- 映射文件 -->
 <!--
      foreach 元素: collection属性:表示要迭代的集合或数组【的类型,若是通过Parm注解,可以直接写上Map中的key,而不用填写类型】
                    open属性:在集合迭代之前,要拼接的符号   close 属性:在集合迭代之后要拼接的符号
                    separator属性:迭代的元素之间的分割符号
                    item属性:每个被迭代的元素
                    index属性:迭代的索引
   -->
  <delete id="batchDelete">
      delete from employee where id in
      <foreach collection="ids" open="(" close=")" separator="," item="id">
          #{id}
      </foreach>
  </delete>

■ foreach 举例2:

/* Mapper接口 */
void batchSave(@Param("emps")List<Employee>emps);

  <!-- 映射文件 -->
  <insert id="batchSave">
      insert into employee (name, sn, salary) values
      <foreach collection="emps" separator="," item="e">
          (#{e.name}, #{e.sn}, #{e.salary})
      </foreach>
  </insert>

5、其他(bind,sql,include) 举例-高级分页查询:

■ sql,include 的例子:

<!-- 映射文件 -->
<mapper namespace="com.shan.hello.mapper.EmployeeMapper">
    <sql id="base_where">
        <where>
            <if test="keyword != null">
                <!--and name like #{%name%}; 要使用字符串函数concat进行拼接呀 -->
                <!-- and name like concat('%', #{name}, '%') or sn like concat('%', #{sn},'%'); qo查询对象,也没有属性name,sn呀 -->
                and (name like concat('%', #{keyword}, '%') or sn like concat('%', #{keyword}, '%'))
            </if>
            <if test="minSalary != null">
                and salary >= #{minSalary}
            </if>
            <if test="maxSalary != null">
                and salary &lt;= #{maxSalary}
            </if>
            <if test="deptId > 0">
                and deptId = #{deptId}
            </if>
        </where>
    </sql>

    <select id="queryForList" resultType="Employee">
        select id, name, sn, salary from employee
        <include refid="base_where"/>
    </select>

    <select id="queryForCount" resultType="int">
        select count(id) from employee
        <include refid="base_where"/>
    </select>

</mapper>

■ bind(跟concat一样是用于拼接字符串) 的例子:

<if test="keyword != null">
    <!--and name like #{%name%}; 要使用字符串函数concat进行拼接呀 -->
    <!-- and name like concat('%', #{name}, '%') or sn like concat('%', #{sn},'%'); qo查询对象,也没有属性name,sn呀 -->
    <!-- and (name like concat('%', #{keyword}, '%') or sn like concat('%', #{keyword}, '%')) -->

    <bind name="keywordLike" value="'%' + keyword + '%'"/>
            and (name like #{keywordLike} or sn like #{keywordLike})
</if>