使用动态查询是MyBatis一个很是强大的功能。有时你已经改变WHERE子句条件的基础上你的参数对象的状态。在这种状况下的MyBatis提供了一组能够映射语句中使用,以提升SQL语句的重用性和灵活性的动态SQL标签。html
全部的逻辑是使用一些额外的标签放在:XML文件。下面是一个例子,其中的SELECT语句将努力在两个方面:java
若是想传递一个ID,而后它会返回全部与该ID的记录,mysql
不然,将返回全部雇员ID为NULL的记录。sql
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd"> <sqlMap namespace="Employee"> <select id="findByID" resultClass="Employee"> SELECT * FROM EMPLOYEE <dynamic prepend="WHERE "> <isNull property="id"> id IS NULL </isNull> <isNotNull property="id"> id = #id# </isNotNull> </dynamic> </select> </sqlMap>
可使用<isNotEmpty>标签以下检查条件。在此条件下将增长,只有当经过属性不为空。数据库
.................. <select id="findByID" resultClass="Employee"> SELECT * FROM EMPLOYEE <dynamic prepend="WHERE "> <isNotEmpty property="id"> id = #id# </isNotEmpty> </dynamic> </select> ..................
若是想查询对id和/或雇员的名字选取。SELECT语句以下:apache
.................. <select id="findByID" resultClass="Employee"> SELECT * FROM EMPLOYEE <dynamic prepend="WHERE "> <isNotEmpty prepend="AND" property="id"> id = #id# </isNotEmpty> <isNotEmpty prepend="OR" property="first_name"> first_name = #first_name# </isNotEmpty> </dynamic> </select> ..................
下面的例子将展现如何编写SELECT语句中使用动态SQL。考虑,咱们已经在MySQL下有EMPLOYEE表:dom
CREATE TABLE EMPLOYEE ( id INT NOT NULL auto_increment, first_name VARCHAR(20) default NULL, last_name VARCHAR(20) default NULL, salary INT default NULL, PRIMARY KEY (id) );
此表有以下只有一条记录:ui
mysql> select * from EMPLOYEE; +----+------------+-----------+--------+ | id | first_name | last_name | salary | +----+------------+-----------+--------+ | 1 | Zara | Ali | 5000 | | 2 | Roma | Ali | 3000 | | 3 | Noha | Ali | 7000 | +----+------------+-----------+--------+ 3 row in set (0.00 sec)
要执行读取操做,让咱们在Employee.java文件Employee类,以下所示:this
public class Employee { private int id; private String first_name; private String last_name; private int salary; /* Define constructors for the Employee class. */ public Employee() {} public Employee(String fname, String lname, int salary) { this.first_name = fname; this.last_name = lname; this.salary = salary; } /* Here are the method definitions */ public int getId() { return id; } public String getFirstName() { return first_name; } public String getLastName() { return last_name; } public int getSalary() { return salary; } } /* End of Employee */
要定义使用iBATIS SQL映射语句,咱们将增长在如下文件Employee.xml修改<select>标记和这个标签订义,咱们将定义一个“id”,这将被用于IbatisReadDy.java文件上执行动态SQL的SELECT查询数据库。spa
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd"> <sqlMap namespace="Employee"> <select id="findByID" resultClass="Employee"> SELECT * FROM EMPLOYEE <dynamic prepend="WHERE "> <isNotNull property="id"> id = #id# </isNotNull> </dynamic> </select> </sqlMap>
上面的SELECT语句将努力在两个方面(一)若是想传递一个ID,而后将相应的编号(二)返回的记录,不然将返回全部记录。
文件将应用程序级别的逻辑从Employee表读出的条件记录:
import com.ibatis.common.resources.Resources; import com.ibatis.sqlmap.client.SqlMapClient; import com.ibatis.sqlmap.client.SqlMapClientBuilder; import java.io.*; import java.sql.SQLException; import java.util.*; public class IbatisReadDy{ public static void main(String[] args) throws IOException,SQLException{ Reader rd=Resources.getResourceAsReader("SqlMapConfig.xml"); SqlMapClient smc=SqlMapClientBuilder.buildSqlMapClient(rd); /* This would read all records from the Employee table.*/ System.out.println("Going to read records....."); Employee rec = new Employee(); rec.setId(1); List <Employee> ems = (List<Employee>) smc.queryForList("Employee.findByID", rec); Employee em = null; for (Employee e : ems) { System.out.print(" " + e.getId()); System.out.print(" " + e.getFirstName()); System.out.print(" " + e.getLastName()); System.out.print(" " + e.getSalary()); em = e; System.out.println(""); } System.out.println("Records Read Successfully "); } }
下面是步骤来编译并运行上述应用。请确保已在进行的编译和执行以前,适当地设置PATH和CLASSPATH。
建立Employee.xml如上所示。
建立Employee.java如上图所示,并编译它。
建立IbatisReadDy.java如上图所示,并编译它。
执行IbatisReadDy二进制文件来运行程序。
会获得下面的结果,而且将记录从EMPLOYEE表中读取。
Going to read records..... 1 Zara Ali 5000 Record Reads Successfully
试试上面的例子中经过传递空值做为smc.queryForList(“Employee.findByID”,NULL)。
iBATIS的提供了强大的基于OGNL的表达式来消除其余元素。
if 语句
choose, when, otherwise 语句
where 语句
foreach 语句
最多见的事情在动态SQL是有条件地包括一个where子句的一部分。例如:
<select id="findActiveBlogWithTitleLike" parameterType="Blog" resultType="Blog"> SELECT * FROM BLOG WHERE state = 'ACTIVE. <if test="title != null"> AND title like #{title} </if> </select>
这条语句会提供功能的可选的文本搜索类型。若是没有传递title,那么全部激活的博客将被退回。可是,若是传递一个标题,它会寻找标题以like 给定的条件。
能够包括多个if条件以下:
最多见的事情在动态SQL是有条件地包括一个where子句的一部分。例如:
<select id="findActiveBlogWithTitleLike" parameterType="Blog" resultType="Blog"> SELECT * FROM BLOG WHERE state = 'ACTIVE. <if test="title != null"> AND title like #{title} </if> <if test="author != null"> AND author like #{author} </if> </select>
iBATIS提供了一个选择的元素,它相似于Java的switch语句。这有助于选择不少种状况。
下面的例子将只搜索标题上若是提供,那么只有由做者若是已提供。若是没有提供,让咱们只返回精选的博客:
<select id="findActiveBlogWithTitleLike" parameterType="Blog" resultType="Blog"> SELECT * FROM BLOG WHERE state = 'ACTIVE. <choose> <when test="title != null"> AND title like #{title} </when> <when test="author != null and author.name != null"> AND author like #{author} </when> <otherwise> AND featured = 1 </otherwise> </choose> </select>
若是咱们看一下前面的例子中,若是没有一个条件知足会发生什么事?最终SQL看起来像这样:
SELECT * FROM BLOG WHERE
这会失败,但iBATIS有一个简单的改变一个简单的解决方案,让一切工做正常:
<select id="findActiveBlogLike" parameterType="Blog" resultType="Blog"> SELECT * FROM BLOG <where> <if test="state != null"> state = #{state} </if> <if test="title != null"> AND title like #{title} </if> <if test="author != null> AND author like #{author} </if> </where> </select>
where元素知道只有插入WHERE ,若是有一个由含标签返回的任何内容。此外,若是该内容开头AND或OR,它知道剥离其关闭。
foreach元素是很是强大的,并容许你指定一个集合,声明能够在元素的体内可用于项目和索引变量。
它也容许你指定打开和关闭的字符串,并添加一个分隔符放置在迭代之间。能够创建一个IN条件以下:
<select id="selectPostIn" resultType="domain.blog.Post"> SELECT * FROM POST P WHERE ID in <foreach item="item" index="index" collection="list" open="(" separator="," close=")"> #{item} </foreach> </select>
系列文章: