日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > 数据库 >内容正文

数据库

SQL语句构建器类

發(fā)布時(shí)間:2023/12/3 数据库 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SQL语句构建器类 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

轉(zhuǎn)載自??SQL語(yǔ)句構(gòu)建器類

問題

Java程序員面對(duì)的最痛苦的事情之一就是在Java代碼中嵌入SQL語(yǔ)句。這么來(lái)做通常是由于SQL語(yǔ)句需要?jiǎng)討B(tài)來(lái)生成-否則可以將它們放到外部文件或者存儲(chǔ)過程中。正如你已經(jīng)看到的那樣,MyBatis在它的XML映射特性中有一個(gè)強(qiáng)大的動(dòng)態(tài)SQL生成方案。但有時(shí)在Java代碼內(nèi)部創(chuàng)建SQL語(yǔ)句也是必要的。此時(shí),MyBatis有另外一個(gè)特性可以幫到你,在減少典型的加號(hào),引號(hào),新行,格式化問題和嵌入條件來(lái)處理多余的逗號(hào)或 AND 連接詞之前。事實(shí)上,在Java代碼中來(lái)動(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";

The Solution

MyBatis 3提供了方便的工具類來(lái)幫助解決該問題。使用SQL類,簡(jiǎn)單地創(chuàng)建一個(gè)實(shí)例來(lái)調(diào)用方法生成SQL語(yǔ)句。上面示例中的問題就像重寫SQL類那樣:

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

該例中有什么特殊之處?當(dāng)你仔細(xì)看時(shí),那不用擔(dān)心偶然間重復(fù)出現(xiàn)的"AND"關(guān)鍵字,或者在"WHERE"和"AND"之間的選擇,抑或什么都不選。該SQL類非常注意"WHERE"應(yīng)該出現(xiàn)在何處,哪里又應(yīng)該使用"AND",還有所有的字符串鏈接。

SQL類

這里給出一些示例:

// Anonymous inner class public String deletePersonSql() {return new SQL() {{DELETE_FROM("PERSON");WHERE("ID = #{id}");}}.toString(); }// Builder / Fluent style public String insertPersonSql() {String sql = new SQL().INSERT_INTO("PERSON").VALUES("ID, FIRST_NAME", "#{id}, #{firstName}").VALUES("LAST_NAME", "#{lastName}").toString();return sql; }// With conditionals (note the final parameters, required for the anonymous inner class to access them) 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(); } 方法描述
  • SELECT(String)
  • SELECT(String...)
開始或插入到?SELECT子句。 可以被多次調(diào)用,參數(shù)也會(huì)添加到?SELECT子句。 參數(shù)通常使用逗號(hào)分隔的列名和別名列表,但也可以是數(shù)據(jù)庫(kù)驅(qū)動(dòng)程序接受的任意類型。
  • SELECT_DISTINCT(String)
  • SELECT_DISTINCT(String...)
開始或插入到?SELECT子句, 也可以插入?DISTINCT關(guān)鍵字到生成的查詢語(yǔ)句中。 可以被多次調(diào)用,參數(shù)也會(huì)添加到?SELECT子句。 參數(shù)通常使用逗號(hào)分隔的列名和別名列表,但也可以是數(shù)據(jù)庫(kù)驅(qū)動(dòng)程序接受的任意類型。
  • FROM(String)
  • FROM(String...)
開始或插入到?FROM子句。 可以被多次調(diào)用,參數(shù)也會(huì)添加到?FROM子句。 參數(shù)通常是表名或別名,也可以是數(shù)據(jù)庫(kù)驅(qū)動(dòng)程序接受的任意類型。
  • JOIN(String)
  • JOIN(String...)
  • INNER_JOIN(String)
  • INNER_JOIN(String...)
  • LEFT_OUTER_JOIN(String)
  • LEFT_OUTER_JOIN(String...)
  • RIGHT_OUTER_JOIN(String)
  • RIGHT_OUTER_JOIN(String...)
基于調(diào)用的方法,添加新的合適類型的?JOIN子句。 參數(shù)可以包含由列命和join on條件組合成標(biāo)準(zhǔn)的join。
  • WHERE(String)
  • WHERE(String...)
插入新的?WHERE子句條件, 由AND鏈接。可以多次被調(diào)用,每次都由AND來(lái)鏈接新條件。使用?OR()?來(lái)分隔OR。
OR()使用OR來(lái)分隔當(dāng)前的?WHERE子句條件。 可以被多次調(diào)用,但在一行中多次調(diào)用或生成不穩(wěn)定的SQL。
AND()使用AND來(lái)分隔當(dāng)前的?WHERE子句條件。 可以被多次調(diào)用,但在一行中多次調(diào)用或生成不穩(wěn)定的SQL。因?yàn)?WHERE?和?HAVING?二者都會(huì)自動(dòng)鏈接?AND, 這是非常罕見的方法,只是為了完整性才被使用。
  • GROUP_BY(String)
  • GROUP_BY(String...)
插入新的?GROUP BY子句元素,由逗號(hào)連接。 可以被多次調(diào)用,每次都由逗號(hào)連接新的條件。
  • HAVING(String)
  • HAVING(String...)
插入新的?HAVING子句條件。 由AND連接。可以被多次調(diào)用,每次都由AND來(lái)連接新的條件。使用?OR()?來(lái)分隔OR.
  • ORDER_BY(String)
  • ORDER_BY(String...)
插入新的?ORDER BY子句元素, 由逗號(hào)連接。可以多次被調(diào)用,每次由逗號(hào)連接新的條件。
DELETE_FROM(String)開始一個(gè)delete語(yǔ)句并指定需要從哪個(gè)表刪除的表名。通常它后面都會(huì)跟著WHERE語(yǔ)句!
INSERT_INTO(String)開始一個(gè)insert語(yǔ)句并指定需要插入數(shù)據(jù)的表名。后面都會(huì)跟著一個(gè)或者多個(gè)VALUES() or INTO_COLUMNS() and INTO_VALUES()。
  • SET(String)
  • SET(String...)
針對(duì)update語(yǔ)句,插入到"set"列表中
UPDATE(String)開始一個(gè)update語(yǔ)句并指定需要更新的表明。后面都會(huì)跟著一個(gè)或者多個(gè)SET(),通常也會(huì)有一個(gè)WHERE()。
VALUES(String, String)插入到insert語(yǔ)句中。第一個(gè)參數(shù)是要插入的列名,第二個(gè)參數(shù)則是該列的值。
INTO_COLUMNS(String...)Appends columns phrase to an insert statement. This should be call INTO_VALUES() with together.
INTO_VALUES(String...)Appends values phrase to an insert statement. This should be call INTO_COLUMNS() with together.

Since version 3.4.2, you can use variable-length arguments as follows:

public String selectPersonSql() {return new SQL().SELECT("P.ID", "A.USERNAME", "A.PASSWORD", "P.FULL_NAME", "D.DEPARTMENT_NAME", "C.COMPANY_NAME").FROM("PERSON P", "ACCOUNT A").INNER_JOIN("DEPARTMENT D on D.ID = P.DEPARTMENT_ID", "COMPANY C on D.COMPANY_ID = C.ID").WHERE("P.ID = A.ID", "P.FULL_NAME like #{name}").ORDER_BY("P.ID", "P.FULL_NAME").toString(); }public String insertPersonSql() {return new SQL().INSERT_INTO("PERSON").INTO_COLUMNS("ID", "FULL_NAME").INTO_VALUES("#{id}", "#{fullName}").toString(); }public String updatePersonSql() {return new SQL().UPDATE("PERSON").SET("FULL_NAME = #{fullName}", "DATE_OF_BIRTH = #{dateOfBirth}").WHERE("ID = #{id}").toString(); }

SqlBuilder 和 SelectBuilder (已經(jīng)廢棄)

在3.2版本之前,我們使用了一點(diǎn)不同的做法,通過實(shí)現(xiàn)ThreadLocal變量來(lái)掩蓋一些導(dǎo)致Java DSL麻煩的語(yǔ)言限制。但這種方式已經(jīng)廢棄了,現(xiàn)代的框架都?xì)g迎人們使用構(gòu)建器類型和匿名內(nèi)部類的想法。因此,SelectBuilder 和 SqlBuilder 類都被廢棄了。

下面的方法僅僅適用于廢棄的SqlBuilder 和 SelectBuilder 類。

方法描述
BEGIN()?/RESET()這些方法清空SelectBuilder類的ThreadLocal狀態(tài),并且準(zhǔn)備一個(gè)新的構(gòu)建語(yǔ)句。開始新的語(yǔ)句時(shí),?BEGIN()讀取得最好。 由于一些原因(在某些條件下,也許是邏輯需要一個(gè)完全不同的語(yǔ)句),在執(zhí)行中清理語(yǔ)句?RESET()讀取得最好。
SQL()返回生成的?SQL()?并重置?SelectBuilder?狀態(tài) (好像?BEGIN()?或?RESET()?被調(diào)用了). 因此,該方法只能被調(diào)用一次!

SelectBuilder 和 SqlBuilder 類并不神奇,但是知道它們?nèi)绾喂ぷ饕彩呛苤匾摹?SelectBuilder 使用 SqlBuilder 使用了靜態(tài)導(dǎo)入和ThreadLocal變量的組合來(lái)開啟整潔語(yǔ)法,可以很容易地和條件交錯(cuò)。使用它們,靜態(tài)導(dǎo)入類的方法即可,就像這樣(一個(gè)或其它,并非兩者):

import static org.apache.ibatis.jdbc.SelectBuilder.*; import static org.apache.ibatis.jdbc.SqlBuilder.*;

這就允許像下面這樣來(lái)創(chuàng)建方法:

/* DEPRECATED */ public String selectBlogsSql() {BEGIN(); // Clears ThreadLocal variableSELECT("*");FROM("BLOG");return SQL(); }/* DEPRECATED */ private String selectPersonSql() {BEGIN(); // Clears ThreadLocal variableSELECT("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(); }

?

總結(jié)

以上是生活随笔為你收集整理的SQL语句构建器类的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。