MyBatis: 动态SQL


动态SQL,是指SQL语句不是硬编码到代码中的,而是程序根据不同情况生成不同的SQL语句。MyBatis中动态SQL的内容还是挺多的,本文只做简单的介绍。更多内容请参考官方的《动态SQL》

本节示例代码在 mybatis-demo-011

数据准备

数据准备

user表的默认内容如下:

mysql> select * from user;
+----+--------+----------------+----------+
| id | name   | email          | password |
+----+--------+----------------+----------+
|  1 | letian | letian@111.com | 123      |
|  2 | xiaosi | xiaosi@111.com | 123      |
+----+--------+----------------+----------+

项目结构

使用 IDEA 创建 gradle 项目,最终结构如下:

示例1

在 UserMapper接口增加方法

/**
 * 根据用户名和密码查询用户。用户名可选
 */
User findByName(@Param("name") String name, @Param("optionalPassword") String password);

findByName 根据用户名和密码查询用户,其中用户名是必须的,密码是可选的。也就是,若没有密码,则SQL查询条件中不会有密码的判断。

在 UserMapper.xml 增加映射

<select id="findByName" resultType="bean.User">
    select * from blog_db.user
    where name=#{name}
    <if test="optionalPassword != null">
        and password = #{optionalPassword}
    </if>
</select>

<if>中判断 optionalPassword 是否为空,若不为空,则将and password = #{optionalPassword}作为SQL的一部分。

在Main类中增加示例代码

@Test
public void test_01() throws IOException {
    try (SqlSession sqlSession = getSqlSession()) {
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = userMapper.findByName("letian", null);
        log.info("{}", user);
    }
}

@Test
public void test_02() throws IOException {
    try (SqlSession sqlSession = getSqlSession()) {
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = userMapper.findByName("letian", "1234");
        log.info("{}", user);
    }
}

运行 test_01 ,输出:

 INFO [main] - User(id=1, name=letian, email=letian@111.com, password=123)

运行 test_02 ,输出:

 INFO [main] - null

示例2

在 UserMapper接口增加方法

/**
 * 根据查询条件查询所有符合要求的用户
 */
List<User> find(User queryCondition);

在 UserMapper.xml 增加映射

<select id="find" parameterType="bean.User" resultType="bean.User">
    select * from blog_db.user
    <where>
        <if test="id != null">
            and id = #{id}
        </if>
        <if test="name != null">
            and name = #{name}
        </if>
        <if test="email != null">
            and email = #{email}
        </if>
        <if test="password != null">
            and password = #{password}
        </if>
    </where>
</select>

这里用了 <where><if>,每个<if>中判断某个字段是否有值,若有值,则在查询条件中增加该字段的判等。注意,每个<if>中的最前面都是and,会不会动态生成的SQL中出现where and 这种错误的SQL?不会,mybatis会处理好这种情况。

在Main类中增加示例代码

@Test
public void test_03() throws IOException {
    try (SqlSession sqlSession = getSqlSession()) {
        User queryCondition = new User();
        queryCondition.setId(1L);
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<User> userList = userMapper.find(queryCondition);
        log.info("{}", userList);
    }
}

@Test
public void test_04() throws IOException {
    try (SqlSession sqlSession = getSqlSession()) {
        User queryCondition = new User();
        queryCondition.setPassword("123");
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<User> userList = userMapper.find(queryCondition);
        log.info("{}", userList);
    }
}

test_03中查询条件给了id,运行结果为:

 INFO [main] - [User(id=1, name=letian, email=letian@111.com, password=123)]

test_03`中查询条件给了password,运行结果为:

 INFO [main] - [User(id=1, name=letian, email=letian@111.com, password=123), User(id=2, name=xiaosi, email=xiaosi@111.com, password=123)]

得到两条记录,符合预期 😁



(本文完)


MyBatis 教程