转载

MyBatis知多少(25)动态SQL

使用动态查询是MyBatis一个非常强大的功能。有时你已经改变WHERE子句条件的基础上你的参数对象的状态。在这种情况下的MyBatis提供了一组可以映射语句中使用,以提高SQL语句的重用性和灵活性的动态SQL标签。

所有的逻辑是使用一些额外的标签放在:XML文件。下面是一个例子,其中的SELECT语句将努力在两个方面:

  • 如果想传递一个ID,然后它会返回所有与该ID的记录,

  • 否则,将返回所有雇员ID为NULL的记录。

<?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语句如下:

.................. <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> .................. 

例如:动态SQL

下面的例子将展示如何编写SELECT语句中使用动态SQL。考虑,我们已经在MySQL下有EMPLOYEE表:

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) ); 

此表有如下只有一条记录:

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 POJO 类:

要执行读取操作,让我们在Employee.java文件Employee类,如下所示:

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 */

Employee.xml 文件:

要定义使用iBATIS SQL映射语句,我们将增加在以下文件Employee.xml修改<select>标记和这个标签定义,我们将定义一个“id”,这将被用于IbatisReadDy.java文件上执行动态SQL的SELECT查询数据库。

<?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,然后将相应的编号(二)返回的记录,否则将返回所有记录。

IbatisReadDy.java 文件:

文件将应用程序级别的逻辑从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 表达式

iBATIS的提供了强大的基于OGNL的表达式来消除其他元素。

  • if 语句

  • choose, when, otherwise 语句

  • where 语句

  • foreach 语句

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> </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> 

choose, when, otherwise 语句:

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> 

where 语句:

如果我们看一下前面的例子中,如果没有一个条件满足会发生什么事?最终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语句:

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> 
正文到此结束
Loading...