前面的文章中一直介绍的都是静态sql,在实际开发过程中,我们会遇到条件查询的需求,根据所给的多个条件查询,mybatis提供了动态sql实现方法。
需求
- 条件查询员工信息
- 条件:员工id或员工lastName或员工email或员工性别。
相关文件
- Employee.java
public class Employee {
private Integer id;
private String lastName;
private String email;
private String gender;
private Department dept;
public Employee() {
super();
}
public Employee(Integer id, String lastName, String email, String gender) {
super();
this.id = id;
this.lastName = lastName;
this.email = email;
this.gender = gender;
}
public Department getDept() {
return dept;
}
public void setDept(Department dept) {
this.dept = dept;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
@Override
public String toString() {
return "Employee [id=" + id + ", lastName=" + lastName + ", email="
+ email + ", gender=" + gender + "]";
}
}
- 创建接口EmployeeDynamicSQLMapper.java,在接口中定义条件查询方法。
public interface EmployeeDynamicSQLMapper {
public List<Employee> getEmployeeByCondition(Employee employee);
}
- 创建EmployeeDynamicSQLMapper接口对应的sql映射文件EmployeeDynamicSQLMapper.xml。并通过if和where完成条件查询。
<?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="com.fzl.mybatis.dao.EmployeeDynamicSQLMapper">
<select id="getEmployeeByCondition" resultType="com.fzl.mybatis.bean.Employee">
select * from tbl_employee
where
<if test="id!=null">
id=#{id}
</if>
<if test="lastName!=null and lastName!='' ">
and last_name like concat("%",#{lastName},"%")
</if>
<if test="email!=null">
and email=#{email}
</if>
<if test="gender==0 or gender==1">
and gender=#{gender}
</if>
</select>
</mapper>
- 测试
在这里插入代码片public class MyBatisDynamicSQLTest {
public SqlSessionFactory getSqlSessionFactory() throws IOException {
String resource = "MyBatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
return sqlSessionFactory;
}
@Test
public void test1() throws IOException {
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
SqlSession openSession = sqlSessionFactory.openSession();
try{
EmployeeDynamicSQLMapper mapper = openSession.getMapper(EmployeeDynamicSQLMapper.class);
Employee employee = new Employee(3, "u", "236534567@qq.com", "1");
List<Employee> employeeList = mapper.getEmployeeByCondition(employee);
for(Employee e:employeeList){
System.out.println(e);
}
}finally{
openSession.close();
}
}
}
- 测试结果
测试数据的id不为空时,我们可以发现测试成功。但是,将测试的查询的员工信息的id设置为null,重新运行,会发现报错了。
这是因为id为空,他就直接执行lastName和下面的条件查询了,但是其他的条件都是以and开头的,因此会报错。这个问题有三种解决办法。
解决办法1
在where后面加上1=1,给where后面加上1==1,以后的条件都and xxx。
解决办法2
mybatis使用<where></where>
标签来将所有的查询条件包括在内。没有把提升就会将where标签中拼装的sql,多出来的and或者or去掉。
但是,<where></where>
只会去掉第一个多出来的and或者or。有些开发者,喜欢在条件的后面加上and,
这时候这个办法就不管用了,这时我们可以采用第三种解决办法。
解决办法3
使用<trim></trim>
标签来解决。<trim></trim>
标签有一下几个属性,可以通过这些属性来解决add或or在后面的的问题。
prefix=""
:前缀:trim标签体中是整个字符串拼串 后的结果。
prefix给拼串后的整个字符串加一个前缀
prefixOverrides=""
:
前缀覆盖: 去掉整个字符串前面多余的字符
suffix=""
:后缀
suffix给拼串后的整个字符串加一个后缀
suffixOverrides=""
:
后缀覆盖:去掉整个字符串后面多余的字符。
<select id="getEmployeeByConditionByTrim" resultType="com.fzl.mybatis.bean.Employee">
select * from tbl_employee
<!--
prefix="":前缀:trim标签体中是整个字符串拼串 后的结果。
prefix给拼串后的整个字符串加一个前缀
prefixOverrides="":
前缀覆盖: 去掉整个字符串前面多余的字符
suffix="":后缀
suffix给拼串后的整个字符串加一个后缀
suffixOverrides=""
后缀覆盖:去掉整个字符串后面多余的字符
-->
<trim prefix="where" suffixOverrides="and">
<if test="id!=null">
id=#{id} and
</if>
<if test="lastName!=null and lastName!='' ">
last_name like concat("%",#{lastName},"%") and
</if>
<if test="email!=null">
email=#{email} and
</if>
<if test="gender==0 or gender==1">
gender=#{gender}
</if>
</trim>
</select>