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>
微信公众号:CodeAction
Github:https://github.com/codeaction