1 問(wèn)題
Java 程序員面對(duì)的最痛苦的事情之一就是在 Java 代碼中嵌入 SQL 語(yǔ)句。
如你所見(jiàn),MyBatis 在 XML 映射中具備強(qiáng)大的 SQL 動(dòng)態(tài)生成能力。
但有時(shí),我們還是需要在 Java 代碼里構(gòu)建 SQL 語(yǔ)句。
在 Java 代碼中動(dòng)態(tài)生成 SQL 代碼真的就是一場(chǎng)噩夢(mèng)。例如:
String 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";
2?解決方案
MyBatis 3 提供了方便的工具類(lèi)來(lái)幫助解決此問(wèn)題。
借助 SQL 類(lèi),我們只需要簡(jiǎn)單地創(chuàng)建一個(gè)實(shí)例,并調(diào)用它的方法即可生成 SQL 語(yǔ)句。
讓我們來(lái)用 SQL 類(lèi)重寫(xiě)上面的例子:
private String selectPersonSql() {
? return new SQL() {{
? ? 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");
? }}.toString();
}
這個(gè)例子有什么特別之處嗎? 仔細(xì)看一下你會(huì)發(fā)現(xiàn),你不用擔(dān)心可能會(huì)重復(fù)出現(xiàn)的 "AND" 關(guān)鍵字,或者要做出用 "WHERE" 拼接還是 "AND" 拼接還是不用拼接的選擇。 SQL 類(lèi)已經(jīng)為你處理了哪里應(yīng)該插入 "WHERE"、哪里應(yīng)該使用 "AND" 的問(wèn)題,并幫你完成所有的字符串拼接工作。
3?SQL 類(lèi)
這里有一些示例:
// 匿名內(nèi)部類(lèi)風(fēng)格
public String deletePersonSql() {
? return new SQL() {{
? ? DELETE_FROM("PERSON");
? ? WHERE("ID = #{id}");
? }}.toString();
}
// Builder / Fluent 風(fēng)格
public String insertPersonSql() {
? String sql = new SQL()
? ? .INSERT_INTO("PERSON")
? ? .VALUES("ID, FIRST_NAME", "#{id}, #{firstName}")
? ? .VALUES("LAST_NAME", "#{lastName}")
? ? .toString();
? return sql;
}
// 動(dòng)態(tài)條件(注意參數(shù)需要使用 final 修飾,以便匿名內(nèi)部類(lèi)對(duì)它們進(jìn)行訪問(wèn))
public String selectPersonLike(final String id, final String firstName, final String lastName) {
? return new SQL() {{
? ? SELECT("P.ID, P.USERNAME, P.PASSWORD, P.FIRST_NAME, P.LAST_NAME");
? ? FROM("PERSON P");
? ? if (id != null) {
? ? ? WHERE("P.ID like #{id}");
? ? }
? ? if (firstName != null) {
? ? ? WHERE("P.FIRST_NAME like #{firstName}");
? ? }
? ? if (lastName != null) {
? ? ? WHERE("P.LAST_NAME like #{lastName}");
? ? }
? ? ORDER_BY("P.LAST_NAME");
? }}.toString();
}
public String deletePersonSql() {
? return new SQL() {{
? ? DELETE_FROM("PERSON");
? ? WHERE("ID = #{id}");
? }}.toString();
}
public String insertPersonSql() {
? return new SQL() {{
? ? INSERT_INTO("PERSON");
? ? VALUES("ID, FIRST_NAME", "#{id}, #{firstName}");
? ? VALUES("LAST_NAME", "#{lastName}");
? }}.toString();
}
public String updatePersonSql() {
? return new SQL() {{
? ? UPDATE("PERSON");
? ? SET("FIRST_NAME = #{firstName}");
? ? WHERE("ID = #{id}");
? }}.toString();
}