一、前言
什么是动态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条件》
=======欢迎大家拍砖,小手一抖,多多点赞哟!=======
版权声明:本文为博主原创文章,允许转载,但转载必须标明出处。