Mybatis 的映射文件中,平常写的 SQL 都是比较简单的,有些时候业务逻辑复杂时,我们的 SQL是动态变化的,此时我们的简单 SQL 就不能满足要求了,以下就简单讲解常用的几个动态SQL的标签。
【动态 SQL 之if标签】
1.目标
我们根据实体类的不同取值,使用不同的 SQL 语句来进行查询。
比如在 id 如果不为空时可以根据 id查询,如果 username 不为空时还要加入用户名作为条件。这种情况在我们的多条件组合查询中经常会碰到
2.讲解
- QueryVo.java
它的作用专门是用来包装查询参数的。
@AllArgsConstructor
@NoArgsConstructor
@Data
public class QueryVo implements Serializable {
//封装查询对象(参数)
private User user;
}
- UserDao.java
public interface UserDao {
/**
* 根据用户名和用户Id查询用户列表
*/
List<User> findUserListByQueryVo(QueryVo queryVo);
}
- UserDao.xml
<!--根据包装类对象 条件进行查询用户列表-->
<select id="findUserListByQueryVo" resultType="User">
select * from t_user where 1=1
<!--根据判断传入的参数是否为null 来进行查询条件的拼接-->
<if test="user!=null and user.uid>0">
and uid=#{user.uid}
</if>
<if test="user!=null and user.username!=null and user.username.length>0">
and username like concat('%',#{user.username},'%')
</if>
</select>
- 测试
@Test
public void findAllTest01(){
//1.获取sqlSession对象
SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSession();
//2.获取dao接口实例
UserDao userDao = sqlSession.getMapper(UserDao.class);
//3.调用方法
QueryVo queryVo = new QueryVo();
//设置查询参数
User user = new User();
//user.setUid(3);
user.setUsername("w");
queryVo.setUser(user);
List<User> list = userDao.findUserListByQueryVo(queryVo);
System.out.println("list = " + list);
//4.提交事务 关闭对象
SqlSessionFactoryUtils.commitAndClose(sqlSession);
}
3.小结
a. if适合动态多条件查询
b. 注意
【动态 SQL 之where标签】
1.目标
为了简化上面 where 1=1 的条件拼装,我们可以采用标签来简化开发。
2.讲解
修改 UserDao.xml 映射文件如下:
<!--根据包装类对象 条件进行查询用户列表-->
<select id="findUserListByQueryVo2" resultType="User">
select * from t_user
<!--where 表示它里面就进行条件的拼接 自动识别条件拼接 如果有多余的关键字 and、or会自动去除
注意:where只会自动去除多余的关键字 不会自动添加 所以在编写sql语句时关键字and、or不能省略
-->
<where>
<!--根据判断传入的参数是否为null 来进行查询条件的拼接-->
<if test="user!=null and user.uid>0">
and uid=#{user.uid}
</if>
<if test="user!=null and user.username!=null and user.username.length>0">
and username like concat('%',#{user.username},'%')
</if>
</where>
</select>
注意: <where />可以自动处理第一个 and
3.小结
a. where标签用在自己写sql语句时 where关键字不好处理的情况下代替where 1= 1
b. 注意:where只会自动去除多余的关键字但是不会自动添加,所以在编写sql语句时关键字and、or不能省略
【动态标签之foreach标签】
1.目标
foreach标签用于遍历集合,实际开发中会经常用到,属性值多了的话还是难记住
2.讲解
2.1需求
- 传入多个 id 查询用户信息,用下边sql 实现:
select uid ,username ,birthday ,sex, address from t_user WHERE username LIKE '张%' AND (uid =1 OR uid =2 OR uid=6)
这样我们在进行范围查询时,就要将一个集合中的值,作为参数动态添加进来。这样我们将如何进行参数的传递?
- 在QueryVo.java 添加一个集合
public class QueryVo implements Serializable {
//封装查询对象(参数)
private User user;
private List<Integer> ids;
}
- UserDao.java
/**
* 根据用户名和用户Id列表查询用户
*/
List<User> findUserListByQueryVo3(QueryVo queryVo);
- UserDao.xml
<!--根据用户名和用户Id列表查询用户-->
<select id="findUserListByQueryVo3" parameterType="QueryVo" resultType="User">
SELECT uid ,username ,birthday ,sex, address FROM t_user
<where>
<if test="user!=null and user.username!=null and user.username.length>0">
and username like concat('%',#{user.username},'%')
</if>
<if test="ids!=null and ids.size>0">
and uid IN
<!--
foreach标签:循环遍历集合参数 进行sql语句拼接
collection:你要遍历的集合数据
open:表示拼接的内容以什么开头
close:表示拼接的内容以什么结尾
separator:表示遍历元素以什么进行分隔
item:就是集合遍历的每一个元素
-->
<foreach collection="ids" open="(" close=")" separator="," item="id">
#{id}
</foreach>
</if>
</where>
</select>
- 测试
// 需求:查询姓张的并且uid为1 2 6 的用户
@Test
public void findAllTesForeach(){
//1.获取sqlSession对象
SqlSession sqlSession = SqlSessionFactoryUtils.getSqlSession();
//2.获取dao接口实例
UserDao userDao = sqlSession.getMapper(UserDao.class);
//3.调用方法
QueryVo queryVo = new QueryVo();
//设置查询参数
User user = new User();
user.setUsername("张");
List<Integer> ids = new ArrayList<Integer>();
ids.add(1);
ids.add(2);
ids.add(6);
queryVo.setUser(user);
queryVo.setIds(ids);
List<User> list = userDao.findUserListByQueryVo3(queryVo);
System.out.println("list = " + list);
//4.提交事务 关闭对象
SqlSessionFactoryUtils.commitAndClose(sqlSession);
}
3.小结
foreach标签用于遍历集合,它的属性:
- collection:代表要遍历的集合元素,注意编写时不要写#{}
- open:代表语句的开始部分(一直到动态的值之前)
- close:代表语句结束部分
- item:代表遍历集合的每个元素,生成的变量名(随便取)
- sperator:代表分隔符 (动态值之间的分割)
【SQL 片段 】
1.目标
Sql 中可将重复的 sql 提取出来,使用时用 include 引用即可,最终达到 sql 重用的目的。我们先到 UserDao.xml 文件中使用标签,定义出公共部分。
2.讲解
- 使用sql标签抽取
<!--提取共性的sql语句,把这些共性的sql语句称之为 sql片段-->
<sql id="selectUser">
SELECT username,address FROM t_user
</sql>
- 使用include标签引入使用
<!--根据用户名和用户Id列表查询用户-->
<select id="findUserListByQueryVo3" parameterType="QueryVo" resultType="User">
<include refid="selectUser"></include>
<where>
<if test="user!=null and user.username!=null and user.username.length>0">
and username like concat('%',#{user.username},'%')
</if>
<if test="ids!=null and ids.size>0">
and uid IN
<!--
foreach标签:循环遍历集合参数 进行sql语句拼接
collection:你要遍历的集合数据
open:表示拼接的内容以什么开头
close:表示拼接的内容以什么结尾
separator:表示遍历元素以什么进行分隔
item:就是集合遍历的每一个元素
-->
<foreach collection="ids" open="(" close=")" separator="," item="id">
#{id}
</foreach>
</if>
</where>
</select>
- 整个图示