老司机学习MyBatis之如何使用动态SQL之使用if条件

一、前言

什么是动态SQL? 动态SQL有什么作用?
如果你有使用 JDBC 或其他类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句有多么痛苦。拼接的时候要确保不能忘了必要的空格,还要注意省掉列名列表最后的逗号。利用动态 SQL 这一特性可以彻底摆脱这种痛苦。
通常使用动态 SQL 不可能是独立的一部分,MyBatis 使用一种强大的动态 SQL 语言来改进这种情形,这种语言可以被用在任意的 SQL 映射语句中。
动态 SQL 元素和使用 JSTL 或其他类似基于 XML 的文本处理器相似。在 MyBatis 之前的版本中,有很多的元素需要来了解。MyBatis3大大提升了它们,现在用不到原先一半的元素就可以了。MyBatis 采用功能强大的基于 OGNL 的表达式来消除其他元素。

Mybatis的动态SQL功能正是为了解决这种问题, 通过 if, choose, when, otherwise, trim, where, set, foreach标签,可组合成非常灵活的SQL语句,从而提高开发人员的效率。下面我们通过相关案例感受Mybatis动态SQL的魅力吧。

二、案例

定义一个接口类EmpMapper,新增接口方法findEmpByConditions

public interface EmpMapper {
	
	/**
	 * 根据条件查询员工信息
	 * @param id
	 * @return
	 */
	public Emp findEmpByConditions(Emp emp);
}

定义一个EmpMapper.xml文件,配置如下

<?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.queen.mybatis.mapper.EmpMapper">
	<select id="findEmpByConditions" resultType="com.queen.mybatis.bean.Emp">
		select id,emp_name empName,emp_email empEmail, dept_id deptId 
			from t_emp 
			where 
			<if test="id!=null">
				id=#{id}
			</if>
			<if test="empName!=null and empName!=""">
				and emp_name=#{empName}
			</if>
			<if test="empEmail!=null and empEmail.trim()!=""">
				and emp_mail=#{empEmail}
			</if>
			<if test="deptId!=null">
				and dept_id=#{deptId}
			</if>
	</select>
</mapper>

如上,这条语句提供了一些可选的条件查找员工信息的功能。如果传入的id 不为空, 那么才会SQL才拼接id = #{id};如果传入的empName不为空, 那么才会SQL才拼接emp_name= #{empName};实现多条件查询。

新增测试类MyBatisTest,添加测试方法testFindEmpByCondition

@Test
public void testFindEmpByCondition() throws IOException {
	SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
	SqlSession openSession = sqlSessionFactory.openSession();
	try {
		EmpMapper mapper = openSession.getMapper(EmpMapper.class);
		Emp emp = new Emp(1,"ant","[email protected]",null);
		Emp empFind = mapper.findEmpByConditions(emp);
		System.out.println(empFind);
	} finally {
		openSession.close();
	}
}

控制台打印结果如下

select id,emp_name empName,emp_email empEmail, dept_id deptId from t_emp where id=? and emp_name=? and emp_mail=? 
2017-08-12 17:17:18,454 [main] [com.queen.mybatis.mapper.EmpMapper.findEmpByConditions]-[DEBUG] ==> Parameters: 1(Integer), ant(String), queen(String)
2017-08-12 17:17:18,494 [main] [com.queen.mybatis.mapper.EmpMapper.findEmpByConditions]-[DEBUG] <==      Total: 1
Emp [id=1, empName=ant, [email protected], deptId=1]

如上,所有的条件都不为空除了deptId,打印的SQL是select id,emp_name empName,emp_email empEmail, dept_id deptId from t_emp where id=? and emp_name=? and emp_name=? 这样的,少了deptId条件。我们尝试,将deptId不为空,作为参数传递进来,这时候SQL语句又会变成什么样呢?

修改测试方法

Emp emp = new Emp(1,"ant","[email protected]",1);

再次测试,控制台打印结果如下

2017-08-12 17:29:37,925 [main] [com.queen.mybatis.mapper.EmpMapper.findEmpByConditions]-[DEBUG] ==>  Preparing: select id,emp_name empName,emp_email empEmail, dept_id deptId from t_emp where id=? and emp_name=? and emp_name=? and dept_id=? 
2017-08-12 17:29:37,988 [main] [com.queen.mybatis.mapper.EmpMapper.findEmpByConditions]-[DEBUG] ==> Parameters: 1(Integer), ant(String), ant(String), 1(Integer)

通过if语句的使用,我们实现了参数条件的动态封装拼接SQL,但是这种方式有点小问题哟,不知道细心的您有木有发现,如果当id不为空的时候,SQL语句会变成这样”select id,emp_name empName,emp_email empEmail, dept_id deptId from t_emp where and emp_name=? and emp_mail=? “,不管三七二十一,where条件后直接拼了and,造成SQL语法错误。报错信息如下:

org.apache.ibatis.exceptions.PersistenceException: 
### Error querying database.  Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'and emp_name='queen'
			 
			 
				and emp_name='queen'
			 
			 
				and dept_i' at line 6
### The error may exist in EmpMapper.xml
### The error may involve defaultParameterMap
### The error occurred while setting parameters
### SQL: select id,emp_name empName,emp_email empEmail, dept_id deptId     from t_emp     where                and emp_name=?               and emp_name=?               and dept_id=?
如上,控制台报错,说MySQL语法错误。那么这个时候我们要怎么处理这种问题,这里我们有两种解决方案,可以参考下一节 《老司机学习MyBatis之如何使用动态SQL之使用where条件》


=======欢迎大家拍砖,小手一抖,多多点赞哟!=======

版权声明:本文为博主原创文章,允许转载,但转载必须标明出处。


猜你喜欢

转载自blog.csdn.net/gaomb_1990/article/details/80639917