MyBatis的动态SQL语句这么厉害的!

时间:2021-11-29 04:18:57

MyBatis动态SQL语句,非常实用

MyBatis 的强大特性之一便是它的动态 SQL。简直厉害啦~

if

if 语句比较常用,查询、删除、修改的时候都是可以用到!

其中的 where 1 = 1 仅仅只是为了满足多条件查询页面中不确定的各种因素而采用的一种构造一条正确能运行的动态SQL语句的一种方法。

where 1 = 0 这个条件始终为false,结果不会返回任何数据,只有表结构,可用于快速建表

<!-- 
    测试 if 语句
    id 与之查询方法相对应
    resultType 表示User对象
    test 属性中可以写判断User对象属性的语句
-->

<select id="queryUser1" resultType="User">
    select * from t_user
    where 1=1
    <if test="name != null">
        and name = #{name}
    </if>
    <if test="info != null">
        and info = #{info}
    </if>
</select>

当传入过来的 name 不为空时,则拼接语句 and name = #{name}

当传入过来的 info 不为空时,则拼接语句 and info = #{info}

这样的话 mybatis 就能灵活的帮助我们~

例如:

/**
 *  这里只是部分代码,可以执行查询操作
 */
@Test   
    public void queryUser1() {
        SqlSessionFactory factory = DbUtils.getInstance();
        SqlSession session = factory.openSession();
        IUserDao mapper = session.getMapper(IUserDao.class);
        User user = new User();
        user.setName("张三");
//      user.setInfo("程序员");
        List<User> list = mapper.queryUser1(user);
        list.forEach(e -> System.out.println(e));
    }

输出结果为:User [id=1, name=张三, info=测试员, games=null] (这样mybatis就把我们想要查询的 name = "张三" 的信息给查询出来了)

user.setName("张三"); 这条代码注释,

然后将 user.setInfo("程序员"); 的注释取消, 效果如下:

输出结果: User [id=3, name=李四, info=程序员, games=null]

[QC] DEBUG [main] org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(159) | ==>  Preparing: select * from t_user where 1=1 and info = ? 
[QC] DEBUG [main] org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(159) | ==> Parameters: 程序员(String)
[QC] DEBUG [main] org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(159) | <==      Total: 1
User [id=3, name=李四, info=程序员, games=null]

where

if 可以通过搭配 where 来升级

<select id="queryUser1" resultType="User">
    select * from t_user
    <where>
        <if test="name != null">
            and name = #{name}
        </if>
        <if test="info != null">
            and info = #{info}
        </if>
    </where>
</select>

这样写的话就 mybatis 遇到AND或者OR这些,就能自己处理了

我们传入一个空的 User 对象来测试

public void queryUser1() {
    SqlSessionFactory factory = DbUtils.getInstance();
    SqlSession session = factory.openSession();
    IUserDao mapper = session.getMapper(IUserDao.class);
    User user = new User();
//      user.setName("张三");
//      user.setInfo("程序员");
    List<User> list = mapper.queryUser1(user);
    list.forEach(e -> System.out.println(e));
}

输出:

User [id=1, name=张三, info=测试员, games=null]
User [id=3, name=李四, info=程序员, games=null]
User [id=4, name=王五, info=打酱油, games=null]
User [id=7, name=鲁班, info=射手, games=[王者荣耀, QQ飞车, 刺激战场]]
User [id=8, name=孙悟空, info=刺客, games=[王者荣耀, QQ飞车, 刺激战场]]

choose, when, otherwise

这个见名知意了, 和 Java 中的 switch 差不多的功能

<!-- 
    1.name 不为空,则根据 name 查询
    2.info 不为空,则根据 info 查询
    3.否则根据id降序排列
-->

<select id="queryUser2" parameterType="user" resultType="User">
    select * from t_user where 1=1
        <choose>
            <when test="name != null">
                and name = #{name}
            </when>
            <when test="info != null">
                and info = #{info}
            </when>
            <otherwise>
                order by id desc
            </otherwise>
        </choose>
</select>

set

set 重要是用于更新数据

修改传入的 id 的信息,如果 name不为空,就修改 name

<update id="updateUser">
    update t_user
    <set>
        <if test="name != null">
            name = #{name}
        </if>
        <if test="info != null">
            info = #{info}
        </if>
    </set>
    where id = #{id}
</update>

测试

@Test
public void updateUser() {
    SqlSession session = DbUtils.getInstance().openSession();
    IUserDao mapper = session.getMapper(IUserDao.class);
    User user = new User();
    user.setId(1);
    user.setInfo("set修改了");
    int updateUser = mapper.updateUser(user);
    System.out.println(updateUser);
    session.commit();
}

日志记录

 ==>  Preparing: update t_user SET info = ? where id = ? 
 ==> Parameters: set修改了(String), 1(Integer)
 <==    Updates: 1

trim

trim标记是一个格式化的标记,可以完成set或者是where标记的功能

trim 的属性

属性 说明
prefix 当 trim 中有内容时, 增加 prefix 所指定的前缀
prefixOverrides 当 trim 中有内容时, 去除 prefixOverrides 指定的前缀
suffix 当 trim 中有内容时, 增加 suffix 所指定的后缀
suffixOverrides 当 trim 中有内容时, 去除 suffixOverrides 指定的后缀
<select id="queryUser3" resultType="User">
    select * from t_user
    <trim prefix="where" prefixOverrides="AND|OR">
        <!-- trim可以代替这里的 where 功能           
            <where>
                <if test="name != null">
                    and name = #{name}
                </if>
                <if test="info != null">
                    and info = #{info}
                </if>
            </where> 
        -->
        <if test="name != null">
            and name = #{name}
        </if>
        <if test="info != null">
            and info = #{info}
        </if>
    </trim>
</select>

foreach

foreach用来遍历,遍历的对象可以是数组,也可以是集合。

先测试这条语句

select * from t_user where 1=1 and id in(1,3,4,7)

结果:

1 张三 set修改了
3 李四 程序员
4 王五 打酱油
7 鲁班 射手 王者荣耀;QQ飞车;刺激战场;

//先处理一下接口
public List queryUser5(@Param("ids") List<Integer> ids);

配置文件内的sql

<select id="queryUser5" resultType="User">
    select * from t_user where 1=1
    <if test="ids != null">
    and id in
        <foreach collection="ids" open="(" close=")" item="id" separator=",">
            #{id}
        </foreach>
    </if>
</select>

foreach 属性

属性 说明
collection collection属性的值有三个分别是list、array、map三种
open 前缀
close 后缀
separator 分隔符,表示迭代时每个元素之间以什么分隔
item 表示在迭代过程中每一个元素的别名
index 用一个变量名表示当前循环的索引位置

日志记录

| ==>  Preparing: select * from t_user where 1=1 and id in ( ? , ? , | ==> Parameters: 1(Integer), 3(Integer), 4(Integer), 7(Integer)
| <==      Total: 4

输出

User(id=1, name=张三, info=set修改了, games=null)
User(id=3, name=李四, info=程序员, games=null)
User(id=4, name=王五, info=打酱油, games=null)
User(id=7, name=鲁班, info=射手, games=[王者荣耀, QQ飞车, 刺激战场])