mybatis学习课程-8-SelectBuilder

mybatis学习教程-8-SelectBuilder

SelectBuilder 的秘密
SelectBuilder 类并没有什么神奇的地方,如果您不了解它如何工作,它对我们也没任何好
处。SelectBuilder 使用一组静态导入方法和一个 ThreadLocal 变量来启用一个能够很容易地组
合条件并会注意所有 SQL 格式的语法。例如:
public String selectBlogsSql() {
BEGIN(); // Clears ThreadLocal variable
SELECT("*");
FROM("BLOG");
return SQL();
}
这只是一个您可能只选择静态生成 SQL 的简单例子,下面是一个更复杂的例子:
者不指定任何参数。
属性:type,method。
type 属性指定类的全名,method 属性指
定这个类中的方法名称。注意:下一章
中,我们会讨论 SelectBuilder 类,它
可以用一种更清晰、更易读的方式生成
动态 SQL。
@Param
Parameter
N/A
如果您的映射方法有多个参数,那这个
注解能为方法的每个参数设定一个参数
名称。否则,多个参数会使用它们的顺
序号命名(不包括任何RowBounds 参
数),例如:#{1},#{2}等等,这是默
认的方式。如果使用@Param(“person
“ ) , 则这个参数就被叫做
#{person}。
MyBatis 3 - User Guide
65
private String selectPersonSql() {
BEGIN(); // Clears ThreadLocal variable
SELECT("P.ID, P.USERNAME, P.PASSWORD, P.FULL_NAME");
SELECT("P.LAST_NAME, P.CREATED_ON, P.UPDATED_ON");
FROM("PERSON P");
FROM("ACCOUNT A");
INNER_JOIN("DEPARTMENT D on D.ID = P.DEPARTMENT_ID");
INNER_JOIN("COMPANY C on D.COMPANY_ID = C.ID");
WHERE("P.ID = A.ID");
WHERE("P.FIRST_NAME like ?");
OR();
WHERE("P.LAST_NAME like ?");
GROUP_BY("P.ID");
HAVING("P.LAST_NAME like ?");
OR();
HAVING("P.FIRST_NAME like ?");
ORDER_BY("P.ID");
ORDER_BY("P.FULL_NAME");
return SQL();
}
如果使用字符串连接,上面的 SQL 语句就会像下面这样来生成:
"SELECT P.ID, P.USERNAME, P.PASSWORD, P.FULL_NAME, "
"P.LAST_NAME,P.CREATED_ON, P.UPDATED_ON " +
"FROM PERSON P, ACCOUNT A " +
"INNER JOIN DEPARTMENT D on D.ID = P.DEPARTMENT_ID " +
"INNER JOIN COMPANY C on D.COMPANY_ID = C.ID " +
"WHERE (P.ID = A.ID AND P.FIRST_NAME like ?) " +
"OR (P.LAST_NAME like ?) " +
"GROUP BY P.ID " +
"HAVING (P.LAST_NAME like ?) " +
"OR (P.FIRST_NAME like ?) " +
"ORDER BY P.ID, P.FULL_NAME";
如果您喜欢上面这种语法,那您仍然可以使用它,但是它很容易出错,要注意在每行结束的
地方都加一个空格。即使您喜欢上面的语法,下面的例子毫无争辩地比在java 代码中连接字符串
更简单:
private String selectPersonLike(Person p){
BEGIN(); // Clears ThreadLocal variable
SELECT("P.ID, P.USERNAME, P.PASSWORD, P.FIRST_NAME, P.LAST_NAME");
FROM("PERSON P");
if (p.id != null) {
WHERE("P.ID like #{id}");
}
if (p.firstName != null) {
WHERE("P.FIRST_NAME like #{firstName}");
MyBatis 3 - User Guide
66
}
if (p.lastName != null) {
WHERE("P.LAST_NAME like #{lastName}");
}
ORDER_BY("P.LAST_NAME");
return SQL();
}
上面的例子有什么特别之处呢?如果您仔细观察的话,您会发现您不需要再担心是否会遇外
地加入了重复的“AND”关键字,或者考虑要使用“WHERE”还是“AND”或者两者都使用。上面的
例子生成一个查询所有PERSON记录的语句,查出与ID匹配的、或者与firstName匹配的、或者与
lastName匹配的记录,或者是与上述三种任何组合条件相匹配的记录。SelectBuilder 会知道哪
里需要添加“WHERE”,哪里需要使用“AND”,以及会注意字符串的连接。最重要的是,它几乎
不管您调用这些方法的顺序(只有一个例外就是使用OR()方法)。
您可能已经关注到这两个方法:BEGIN() and SQL()。概括地说,每一个SelectBuilder 方法
都要以BEGIN()开头,以 SQL()结束,这也是生成 SQL 的范围。在BEGIN()和 SQL()之间,您可以
提取 SelectBuilder 的方法来一步一步分解您的逻辑。BEGIN()方法清除了 ThreadLocal 变量以保
证不会有先前残留的内容,SQL()方法装配自从调用 BEGIN()后所有SelectBuilder 方法生成的
SQL 语句。注意:BEGIN()方法有一个同义词方法RESET(),它们做相同的事,在某些情况下使用
RESET()可读性会更强。
要像上面那样使用 SelectBuilder 的方法,您简单地只要使用静态导入就可以了,如:
import static org.mybatis.jdbc.SelectBuilder.*;
一旦被导入,您就能够使用SelectBuilder 类的所有方法。SelectBuilder 类的方法如下:
Method
Description
BEGIN() / RESET()
这个方法清空 SelectBuilder 的 ThreadLocal 状态,并准备好生成
一个新的语句。BEGIN()方法放在句子的开头可读性比较好。RESET()
方法在执行过程中由于一些原因(可能在某些情况下,执行逻辑需
要一个完全不同的语句)清空语句后使用,可读性比较好
SELECT(String)
开始或者追加一个 SELECT 子句。也可被多次调用,参数将会被追
加到 SELECT 语句中。参数通常是用一个逗号分隔的列名和别名字
符串,或者是任何驱动器支持的语法。
SELECT_DISTINCT(String)
开始或者追加一个SELECT 子句,在生成的查询语句中增加关键字
“DISTINCT”。也可被多次调用,参数将会被追加到SELECT 语句
中。参数通常是用一个逗号分隔的列名和别名字符串,或者是任何
驱动器支持的语法。
FROM(String)
开始或者追加一个 FROMT 子句。也可被多次调用,参数将会被追加
到 FROM 语句中。参数通常是一个table 名或者别名,或者是驱动
器支持的语法。
JOIN(String)
INNER_JOIN(String)
LEFT_OUTER_JOIN(String)
增加一个恰当类型的 JOIN 子句,这由调用的方法决定。参数是标准
的由列和条件连接在一起的JOIN 子句。
MyBatis 3 - User Guide
67
SqlBuilder
与SelectBuilder类似,MyBatis 也包含了一个通用的SqlBuilder类,它包含了
SelectBuilder的所有方法,同时也有一些针对inserts, updates, 和deletes 的方法。这个类在
DeleteProvider 、nsertProvider和UpdateProvider (以及SelectProvider )里生成SQL 语句
时非常有用。
要像上面的例子那样使用 SqlBuilder,同样只要使用静态导入就可了,例如:
import static org.mybatis.jdbc.SqlBuilder.*;
SqlBuilder 包含了SelectBuilder 的所有方法, 同时还有一些额外的方法:
Method
Description
RIGHT_OUTER_JOIN(String)
WHERE(String)
追加一个新的条件子句,可以被多次调用,每个子句使用AND 来连
结。如果使用 OR() ,则使用 OR 来分隔。
OR()
使用 OR 来分隔WHERE 条件子句,可以被多次调用,但是对某一行调
用超过一次则可能生成错误的 SQL 语句。
AND()
使用 AND 来分隔WHERE 条件子句,可以被多次调用,但是对某一行
调用超过一次会产生错误的SQL 语句。因此WHERE 和 HAVING 都会自
动的添加 AND 来连结语句。这个方法的使用非常罕见,包含这个方
法的原因可能就为了生成 SQL 语句语法上的完整性。
GROUP_BY(String)
追加一个 GROUP BY 子句,可以被多次调用,每个子句由逗号连接。
HAVING(String)
追加一个 HAING 条件子句,可以被多次调用,每个子句由AND 连
接。如果使用 OR() ,则使用 OR 来分隔。
ORDER_BY(String)
追加一个 ORDER BY 子句,可以被多次调用,每个子句由逗号分隔。
SQL()
SQL()方法返回生成的 SQL 语句,并且重新设置 SelectBuilder 状
态(只有 BEGIN() 或者 RESET()已经被调用时)。因此,这个方法
只能被调用一次。
Method
Description
DELETE_FROM(String)
开始一个 delete 语句,同时指定要删除的表。通常它应该在WHERE
语句前被调用。
INSERT_INTO(String)
开始一个插入语句,同时指定插入的表。它应该在一个或者多个
VALUES()方法之前被调用。
SET(String)
追加“set”列表到更新语句中。
UPDATE(String)
开始一个更新语句,同时指定更新的表。在一个或者多个SET()方
法前被调用,通常情况下,WHERE()方法连接在它后面。
VALUES(String, String)
追加一个插入语句,第一个参数是要插入的一列名,第二个参数是要
插入的值。
MyBatis 3 - User Guide
68
下面是些例子:
public String deletePersonSql() {
BEGIN(); // Clears ThreadLocal variable
DELETE_FROM("PERSON");
WHERE("ID = ${id}");
return SQL();
}
public String insertPersonSql() {
BEGIN(); // Clears ThreadLocal variable
INSERT_INTO("PERSON");
VALUES("ID, FIRST_NAME", "${id}, ${firstName}");
VALUES("LAST_NAME", "${lastName}");
return SQL();
}
public String updatePersonSql() {
BEGIN(); // Clears ThreadLocal variable
UPDATE("PERSON");
SET("FIRST_NAME = ${firstName}");
WHERE("ID = ${id}");
return SQL();
}