MyBatis06_动态SQL语句

本教程源码请访问:tutorial_demo
之前在MyBatis持久层接口映射配置文件中,我们使用的SQL语句都是比较简单的,有时候业务逻辑复杂,SQL语句是动态变化的,前面学习的SQL语句就不能满足要求了。

一、if标签

我们根据实体类的不同取值,使用不同的SQL语句来进行查询。比如,username不为空时,根据username进行查询,address不为空时,根据address进行查询。这种多条件组合查询经常会碰到。

1.1、 持久层接口IUserDao

List<User> findByUser(User user);

1.2 持久层映射配置文件IUserDao.xml

<select id="findByUser" resultType="org.codeaction.domain.User">
    select * from user where 1=1
    <if test="username != null and username != ''">
        and username like #{username}
    </if>
    <if test="address != null and address != ''">
        and address like #{address}
    </if>
</select>

if标签中test属性中写的是对象的属性名,如果是封装的对象,这里要使用OGNL表达式的写法。注意这里的where 1=1。

1.3 测试方法

@Test
public void testFindByUser() {
    IUserDao userDao = session.getMapper(IUserDao.class);
    User user = new User();
    user.setUsername("%王%");
    user.setAddress("北京");

    List<User> users = userDao.findByUser(user);
    users.forEach(System.out::println);
}

运行测试方法,控制台输出如下:

User{id=41, username='王一', birthday=Tue Dec 27 17:47:08 CST 2011, sex='男', address='北京'}

二、where标签

上面的案例使用的where 1=1,我们可以使用where标签来进行简化。

<select id="findByUser" resultType="org.codeaction.domain.User">
    select * from user
    <where>
        <if test="username != null and username != ''">
            and username like #{username}
        </if>
        <if test="address != null and address != ''">
            and address like #{address}
        </if>
    </where>
</select>

三、foreach标签

查询地址的北京或拉萨的用户,SQL如下:

select * from user where address in ('北京', '拉萨');
select * from user where address = '北京' or  address = '拉萨';

如果我们需要对一个范围进行查询,就需要将集合中的值作为参数添加进来。

3.1、 持久层接口IUserDao

List<User> findByAddress(List<String> list);

3.2、持久层映射配置文件IUserDao.xml

<select id="findByAddress" resultType="org.codeaction.domain.User" parameterType="list">
    select * from user
    <where>
        <if test="list != null and list.size() >= 0">
			<!--
				foreach标签用于遍历集合。
				collection:代表要遍历的集合元素,注意编写时不要写#{};
				open:代表语句的开始部分;
				close:代表结束部分;
				item:代表遍历集合的每个元素,生成的变量名;
				sperator:代表分隔符。
			-->
            <foreach collection="list" item="addr" open="address in (" close=")" separator=",">
                #{addr}
            </foreach>
        </if>
    </where>
</select>

3.3、测试方法

@Test
public void testFindByAddress() {
    IUserDao userDao = session.getMapper(IUserDao.class);
    List<String> list = new ArrayList<String>();
    list.add("北京");
    list.add("拉萨");

    List<User> users = userDao.findByAddress(list);
    users.forEach(System.out::println);
}

运行测试方法,控制台输出如下:

User{id=41, username='王一', birthday=Tue Dec 27 17:47:08 CST 2011, sex='男', address='北京'}
User{id=46, username='老王', birthday=Sat Aug 07 17:37:26 CST 1999, sex='女', address='拉萨'}

四、SQL片段

我们在前面的学习中发现持久层映射配置文件有一些重复的SQL语句,我们可以通过定义SQL片段的方式把重复的SQL语句抽取出来,通过引用的方式在其他地方引用SQL片段。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.codeaction.dao.IUserDao">
    <!-- 定义SQL片段 -->
    <sql id="defaultSQL">
        select * from user
    </sql>
    <!-- 配置查询所有 -->
    <select id="findAll" resultType="org.codeaction.domain.User">
        <!-- 引用SQL片段 -->
        <include refid="defaultSQL"></include>
    </select>
    <select id="findByUser" resultType="org.codeaction.domain.User">
        <!-- 引用SQL片段 -->
        <include refid="defaultSQL"></include>
        <where>
            <if test="username != null and username != ''">
                and username like #{username}
            </if>
            <if test="address != null and address != ''">
                and address like #{address}
            </if>
        </where>
    </select>

    <select id="findByAddress" resultType="org.codeaction.domain.User" parameterType="list">
        <!-- 引用SQL片段 -->
        <include refid="defaultSQL"></include>
        <where>
            <if test="list != null and list.size() >= 0">
                <foreach collection="list" item="addr" open="address in (" close=")" separator=",">
                    #{addr}
                </foreach>
            </if>
        </where>
    </select>
</mapper>
posted @ 2020-05-19 10:55  CodeAction  阅读(140)  评论(0编辑  收藏  举报