Java康复性训练——MyBatis3(3)

2016/7/20 posted in  Java  

接上篇,继续对Mybatis的使用进行介绍。

代码展示:Github地址

动态SQL

在实际开发过程中,静态的SQL写法并没有什么灵活性。当我们对User进行检索时,可能是依据id,role,username等等参数,如果使用静态SQL语句,我们就需要重复写大量的代码。为了解决这类问题,我们引入动态SQL。

Mybatis对动态SQL有很不错的支持,增加了很多扩展。

IF标签

当我们开发过程中,遇到上述的多条件或指定条件查询时,我们可以使用IF标签来扩展。
以实现一个用户检索为例:

  1. 在UserMapper接口中定义查询方法:public List<User> searchUser(Map<String, Object> searchMap);
  2. 在UserMapper.xml中对接口进行实现:

        <select id="searchUser" parameterType="Map" resultMap="UserResult">
        select * from user where 1=1
        <if test="username!=null">
            and username like #{username}
        </if>
        <if test="id!=null">
            and id=#{id}
        </if>
        <if test="role!=null">
            and roleId=#{role.id}
        </if>
    </select>
    
  3. 调用查询,传入查询条件的Map即可。

    public void testSearch(){
        Role role = new Role();
        role.setId(1);
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("role", role);  
        List<User> userList = userMapper.searchUser(map);
        for(User user:userList){
            System.out.println(user);
        }   
    }
    

Choose、when和otherwise标签

上面的IF标签类似于我们结构控制的IF语句,那么现在介绍的这个标签就类似于我们的结构控制中的Switch-Case语句。
当我们需要对条件进行限制的时候,我们就可以使用这个标签。标签的结构如下:

<choose>
    <when test=""></when>
    <when test=""></when>
    <otherwise></otherwise>
</choose>

where标签

where条件是对Where语句的一个优化,可以自动给SQL语句加上Where。如果Where子句以and或者or开头时,则自动删除第一个and或or。

    <select id="searchUser" parameterType="Map" resultMap="UserResult">
        select * from user 
        <where>
            <if test="username!=null">
                and username like #{username}
            </if>
            <if test="id!=null">
                and id=#{id}
            </if>
            <if test="role!=null">
                and roleId=#{role.id}
            </if>
        </where>
    </select>

trim标签

与where语句类似,给语句增加前后缀。

Foreach标签

用于拼接SQL语句的in语句,对传入的集合进行遍历。集合名称collectionName,元素名称itemName,拼接时以(开始,以结束,用分割。

<foreach collection="collectionName" item="itemName" open="(" close=")" separator=",">
#{itemName}
</foreach>

set标签

和where子句类似,用于update语句。可以自动加上set,并自动删除最后一个

<update id="updateUser" parameterType="User">
        update user 
        <set>
            <if test="username!=null">
                username=#{username},
            </if>
            <if test="password!=null">
                password=#{password},
            </if>
            <if test="role!=null">
                roleId=#{role.id},
            </if>
        </set>
        where id=#{id}
</update>

处理CLOB、BLOB类型数据

  • BLOB映射为byte[],CLOB映射为String
  • 数据插入和读取时,参照对应的映射类型进行处理即可。

传入多个输入参数

  • 使用<key,value>键值对的Map进行传递
  • 在SQL拼接时,直接使用#{param1}、#{param2}...来获取

MyBatis分页

  • 逻辑分页,即把所有的数据加入内存,每次取出若干条。通过RowBounds对象即可实现(需要指定offset,limit两个值)
  • 物理分页,使用limit子句来实现分页

MyBatis缓存

MyBatis默认情况下,启用一级缓存,即同一个SqlSession接口对象调用了相同的select语句,则直接会从缓存中返回结果,而不再查询一次数据库。
开发者可以自己配置二级缓存,二级缓存是全局的。默认情况下,select使用缓存,insert、update、delete不使用缓存。

使用注解配置SQL映射器

基本映射语句

  1. @Insert:声明在插入的接口上方,参数为sql语句,和XML配置时相同;
  2. @Update:同上;
  3. @delete:同上;
  4. @select:简单的返回单个对象时,和在查询方法上配置sql语句即可。
  5. @select:当需要返回集合时:

    @Select("select * from user where id=#{id}")
    @Results({
        @Result(id=true,column="id",property="id"),
        @Result(column="username",property="username"),
        @Result(column="password",property="password"),
    })
    public User getUserById(Integer id);
    

关系映射

  1. 一对一映射:@Result(column="roleId",property="role" one=@One(select="site.zhanjingbo.mapper.RoleMapper.getRoleById"));

  2. 一对多: @Result(column="id",property="userList" many=@Many(select="site.zhanjingbo.mapper.StudentMapper.getUserbyRole"))

动态SQL

实现比较复杂,建议使用XML实现。使用注解效果不是很好。