Mybatis(四)之动态SQL

在实际场景中,我们需要根据业务使用sql语句,这时动态sql语句就能很大程度上提高代码重用性,使编程更加灵活

  • if
  • where
  • trim
  • set
  • foreach
  • bind
  • choose
  • when
  • otherwise

if和where

我们先来看看示例

// mapper接口
public interface UserMapper {
    public List findUserListByUserInfo(User user);
}

//mapper映射文件
<select id="findUserListByUserInfo" parameterType="com.zyj.mybatis.po.User" resultType="com.zyj.mybatis.po.User">
        select * from user where username like '%${username}%' and sex = #{sex}
select>

//测试代码
@Test
public void testFindUserListByUserInfo() throws IOException {
    //......
    // 调用mapper方法
    User userCondition = new User();
    userCondition.setUsername("小明");
    userCondition.setSex("1");
    List list = userMapper.findUserListByUserInfo(userCondition);
    //......
}
问题:以上代码可以正常运行,但是存在硬编码问题,灵活性差
比如只能固定使用username和sex两个字段作为条件来查询,如果增加或缺少字段,就会导致程序运行结果与预期不符
解决方法:使用Mybatis提供的标签,实现动态SQL语句
我们可以修改下mapper映射文件

<select id="findUserListByUserInfo" parameterType="com.zyj.mybatis.po.User" resultType="com.zyj.mybatis.po.User">
    select * from user 
    
    <where>
        
        
        <if test="username != null and username != ''">
            and username like '%${username}%'
        if>
        <if test="sex != null and sex != ''">
            and sex = #{sex}
        if>
    where>
select>

修改后,Mybatis可以自行根据条件创建sql语句

另外还支持将通用SQL抽取出来,提高代码重用性




<sql id="whereClause">
    <if test="user != null">
        <if test="username != null and username != ''">
            AND username LIKE '%${username}%'
        if>
        <if test="sex != null and sex != ''">
            AND sex = #{sex}
        if>
    if>
sql>

<select id="findUserListByUserInfo" parameterType="com.zyj.mybatis.po.User" resultType="com.zyj.mybatis.po.User">
    select * from user 
    <where>
        
        <include refid="whereClause" />
    where>
select>

trim

上面的where标签,其实用trim可以表示如下:

"WHERE" prefixOverrides="AND | OR ">
    ... 

它的意思就是: 当WHERE后紧随AND或则OR的时候,就去除AND或者OR。 除了WHERE以外, 其实还有一个比较经典的实现,那就是SET。

set

id="updateUser" parameterType="com.dy.entity.User">
    update user set 
    <if test="name != null">
        name = #{name},
    if> 
    <if test="password != null">
        password = #{password},
    if> 
    <if test="age != null">
        age = #{age}
    if> 
    <where>
        <if test="id != null">
            id = #{id}
        if>
        and deleteFlag = 0;
    where>

问题来了: “如果只有name不为null时, 那么这SQL不就成了 update set name = #{name}, where ........? 那name后面那逗号会导致出错啊!”

是的,这时候,就可以用mybatis为我们提供的set标签了。下面是通过set标签改造后:

"updateUser" parameterType="com.dy.entity.User">
       update user
    <set>
        <if test="name != null">name = #{name},if> 
        <if test="password != null">password = #{password},if> 
        <if test="age != null">age = #{age},if> 
    set>
    <where>
        <if test="id != null">
            id = #{id}
        if>
        and deleteFlag = 0;
    where>

这个用trim可表示为:

"SET" suffixOverrides=",">
    ...

WHERE是使用的 prefixOverrides(前缀), SET是使用的 suffixOverrides (后缀), 看明白了吧!

foreach

需求:SELECT * FROM user WHERE id IN (1,10,16)
// mapper接口
public interface UserMapper {
    public List<User> findUserListByIdList(List<Integer> ids);
}

// mapper映射文件
<select id="findUserListByIdList" parameterType="list" resultType="com.zyj.mybatis.po.User">
    select * from user 
    <where>
        <if test="list != null">
            
            
            
            
            
            
            and id in 
            <foreach collection="list" index="index" item="id" open="(" separator="," close=")">
                #{id}
            foreach>
        if>
    where>
    // 拼出来的字符串:where id in (1, 10, 16)
select>

// 测试代码
@Test
public void findUserListByIdList() throws IOException {
    //......
    // 调用mapper方法
    List<Integer> ids = new ArrayList<Integer>();
    ids.add(1);
    ids.add(10);
    ids.add(16);
    List<User> list = mapper.findUserListByIdList(ids);
    //......
}

bind

bind 元素可以从 OGNL 表达式中创建一个变量并将其绑定到上下文。比如:

<select id="selectBlogsLike" resultType="Blog">
    "pattern" value="'%' + _parameter.getTitle() + '%'" />
    SELECT * FROM BLOG
    WHERE title LIKE #{pattern}
select>

你可能感兴趣的:(【框架】Mybatis)