Dynamic SQL
动态SQL是iBATIS的一个非常强大的功能。 有时您必须根据参数对象的状态更改WHERE子句标准。 在这种情况下,iBATIS提供了一组动态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>
您可以使用标记检查条件,如下所示。 只有当传递的属性不为空时,才会添加条件。
..................
<select id="findByID" resultClass="Employee">
SELECT * FROM EMPLOYEE
<dynamic prepend="WHERE ">
<isNotEmpty property="id">
id = #id#
</isNotEmpty>
</dynamic>
</select>
..................
如果您想要一个查询,我们可以在其中选择一个ID和/或一个Employee的名字,您的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示例
以下示例说明如何使用动态SQL编写SELECT语句。 考虑一下,我们在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 |
+----+------------+-----------+--------+
1 row in set (0.00 sec)
Employee POJO Class
要执行读操作,让我们在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 File
要使用iBATIS定义SQL映射语句,我们将在Employee.xml中添加以下修改后的标记,并在此标记定义中,我们将定义一个“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,则返回与该ID对应的记录,否则返回所有记录。
IbatisReadDy.java File
此文件具有应用程序级逻辑,用于从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 ");
}
}
编译和运行 (Compilation and Run)
以下是编译和运行上述软件的步骤。 在继续编译和执行之前,请确保已正确设置PATH和CLASSPATH。
- 创建Employee.xml,如上所示。
- 如上所示创建Employee.java并编译它。
- 如上所示创建IbatisReadDy.java并编译它。
- 执行IbatisReadDy二进制文件来运行程序。
您将获得以下结果,并且将从EMPLOYEE表中读取记录。
Going to read records.....
1 Zara Ali 5000
Record Reads Successfully
通过将null作为smc.queryForList("Employee.findByID", null)传递来尝试上面的示例。
iBATIS OGNL表达式
iBATIS提供了强大的基于OGNL的表达式来消除大多数其他元素。
- if Statement
- choose, when, otherwise Statement
- where Statement
- foreach Statement
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>
此语句提供可选的文本搜索类型的功能。 如果您没有传入标题,则返回所有活动的博客。 但是如果你确实传入一个标题,那么它将寻找具有给定条件的标题。
您可以包含多个if条件,如下所示 -
<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语句的choose元素。 它有助于在众多选项中仅选择一个案例。
以下示例仅按标题搜索(如果提供了一个),然后仅提供作者(如果提供了一个)。 如果两者都没有提供,它只返回精选博客 -
<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,开头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>