Mybatis | 05 Mybatis动态SQL语句
Mybatis动态SQL语句
1. 动态SQL语句
1.1 什么是动态SQL
动态SQL语句是Mybatis的重要特性
在遇到较为复杂的SQL语句时,需要进行SQL拼接,动态SQL可以简化拼接SQL的操作并避免错误
1.2 动态SQL常用标签
- if
- where
- foreach
- trim
- when
- set
- choose
目前使用到前3个后续继续补充
2. < if >
目的:**根据所给条件动态拼接**SQL进行查询
这里的条件可能有可能没有,可能是某一个属性,也可能是多个属性组合
2.1 相关准备
- 新增DAO接口方法
public interface IUserDao{
List<User> findByCondition(User user);
}
2.2 标签配置
使用 if标签 进行条件判断
标签属性:
- test属性指定判断条件
<!--已经注册过别名-->
<select id="findByCondition" parameterType="user" resultType="user">
select * from user where 1=1
<if test="username != null">
<!--所给条件中有用户名就把用户名添加到查询条件中-->
and username = #{username}
</if>
<if test="bonus != null">
<!--所给条件中有奖金就把奖金添加到查询条件中-->
and bonus = #{bonus}
</if>
</select>
2.3 测试
- 使用用户名一个属性查询
@Test
//只有用户名一个查询条件时
public void findByConditionTest(){
User user = new User();
user.setUsername("test");
List<User> users = userDao.findByCondition(user);
for(User u : users){
System.out.println(u);
}
}
查询结果
- 使用用户名和奖金属性查询
@Test
//有用户名和奖金两个查询条件时
public void findByConditionTest(){
User user = new User();
user.setUsername("test");
user.setBonus(1000);
List<User> users = userDao.findByCondition(user);
for(User u : users){
System.out.println(u);
}
}
查询结果
小心别掉坑:SQL语句中的部分无关大小写,实体类中的属性有大小写之分
错误示范:
用户实体类
public class User{
private String userName;
}
映射文件
<select id="findByCondition" parameterType="user" resultType="user">
select * from user where 1=1
<if test="username != null">
and username = #{username}
</if>
</select>
- 判断条件中、SQL语句占位符中的值与实体类属性有关,但这里使用小写
很好,你错了:
Tips:能保证实体类属性和数据库列名相同最好,如果不行要时刻注意属性名!!
3. < where >
3.1 标签配置
使用 where标签 代替SQL语句中动态拼接条件的部分
<select id="findByCondition" parameterType="user" resultType="user">
select * from user
<where>
<if test="username != null">
and username = #{username}
</if>
<if test="bonus != null">
and bonus = #{bonus}
</if>
</where>
</select>
Tips 3.1:where 1=1 和 < where >
似乎只是换了一种条件判断的写法,实际上Mybatis对结果进行简单的处理
例如:
- 只会在至少有一个条件满足时才插入“WHERE”子句
- 若语句的开头为“AND”或“OR”时,Mybatis知道怎么去处理
这些都是之前“where 1=1”没有实现的
4. < foreach >
目的:根据QueryVo中的ID进行子查询
对应的SQL语句为“ select * from user where id in( ) ”
4.1 相关准备
- QueryVo查询条件类
package org.example.domain;
public class QueryVo{
private User user;
private List<Integer> ids;
//省略了get和set方法
}
- 新增DAO接口方法
public interface IUserDao{
List<User> findByIds(QueryVo vo);
}
4.2 标签配置
使用 foreach标签 遍历集合
标签属性:
-
collection属性指定所要遍历的集合
-
open属性指定语句开始的部分
-
close属性指定语句结束的部分
-
item属性代表遍历集合时每个元素的变量名
-
sperator属性指定每个元素之间的分隔符
<select id="findByIds" parameterType="queryvo" resultType="user">
select * from user
<where>
<if test="ids != null and ids.size() > 0">
<foreach collection="ids" open="and id in (" close=")" item="id" seperater=",">
#{id}
</foreach>
</if>
</where>
</select>
Tips:value属性占位符中的属性名由item的变量的决定
4.3 测试
测试方法
@Test
public void findByIdsTest(){
QueryVo vo = new QueryVo();
List<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(2);
list.add(5);
vo.setIds(list);
List<User> users = userDao.findByIds(vo);
for(User user : users){
System.out.println(user);
}
}
查询结果
5. < sql >补充
问题:使用动态SQL语句时每条语句前都要使用“select * from user”
5.1 抽取重复SQL语句
使用 sql标签 抽取重复SQL语句
标签属性:
- id属性唯一标识这一段可复用的SQL语句
<sql id="selectDefault">
select * from user
</sql>
5.2 插入重复的SQL语句
在使用时使用 include标签 引入
标签属性:
- refid属性指定所使用的复用SQL语句的唯一标识
<select id="findAll" resultType="user">
<include refid="selectDefault"/>
</select>