SQL查詢構造器

sqlHelper:SQL查詢構造器

搞了幾年的PHP開發(fā)酬土,接觸到好些PHP框架败潦,數(shù)據(jù)庫模型這塊管行,發(fā)現(xiàn)CodeIgniter框架的語法非常 通俗易懂厨埋,也容易記。

最近在學習Java捐顷,接觸到JFinal框架荡陷,使用起來也非常簡單,有點腳本語言的味道迅涮,但是模型這塊废赞,打算讓它更好玩一些。

于是叮姑,想到把CodeIgniter框架的這套模型語法搬到JFinal框架上來,這樣就可以節(jié)省手寫SQL字符串的時間耘沼。

核心文件

主要用到2個類文件:

(1) SqlHelper.java : 專門用來拼接SQL字符串的,最終輸出完整的SQL語句骚烧;

(2) DbHelper.java : 繼承了SqlHelper類既峡,簡單封裝了JFinal框架執(zhí)行SQL語句的API,讓自己有執(zhí)行SQL語句的能力传惠;

語法如下

查詢[1]

下面的方法用來構建 SELECT 語句泰佳。

select("title,content,date")

該方法用于編寫查詢語句中的 SELECT 子句:

List<Record> list = DbHelper.create()
        .select("title,content,date")
        .findAll("mytable");
// 執(zhí)行: SELECT `title`, `content`, `date`
// FROM `mytable`

注意:如果你要查詢表的所有列浇坐,可以不用寫這個函數(shù),SqlHelper 會自動查詢所有列(SELECT *)黔宛。

select() 方法的第二個參數(shù)可選近刘,如果設置為 FALSE,SqlHelper 將不保護你的 表名和字段名臀晃,這在當你編寫復合查詢語句時很有用觉渴,不會破壞你編寫的語句积仗。

List<Record> list = DbHelper.create()
        .select("(SELECT SUM(payments.amount) FROM payments WHERE payments.invoice_id=4) AS amount_paid", false)
        .findAll("mytable");
// 執(zhí)行:SELECT (SELECT SUM(payments.amount) FROM payments 
// WHERE payments.invoice_id=4) AS amount_paid
// FROM `mytable`

selectMax()

該方法用于編寫查詢語句中的 SELECT MAX(field) 部分寂曹,你可以使用第二個參數(shù)(可選)重命名結果字段回右。

List<Record> list = DbHelper.create()
      .selectMax("age")
      .findAll("members");
// 執(zhí)行:SELECT MAX(`age`) AS `age`
// FROM `members`

List<Record> list = DbHelper.create()
      .selectMax("age", "member_age")
      .findAll("members");
// 執(zhí)行:SELECT MAX(`age`) AS `member_age`
// FROM `members`

selectMin()

該方法用于編寫查詢語句中的 SELECT MIN(field) 部分隆圆,和 selectMax() 方法一樣, 你可以使用第二個參數(shù)(可選)重命名結果字段。

List<Record> list = DbHelper.create()
        .selectMin("age")
        .findAll("members");
// 執(zhí)行:SELECT MIN(`age`) AS `age`
// FROM `members`

selectAvg()

該方法用于編寫查詢語句中的 SELECT AVG(field) 部分潮太,和 selectMax() 方法一樣, 你可以使用第二個參數(shù)(可選)重命名結果字段。

List<Record> list = DbHelper.create()
        .selectAvg("age")
        .findAll("members");
// 執(zhí)行:SELECT MIN(`age`) AS `age`
// FROM `members`

selectSum()

該方法用于編寫查詢語句中的 SELECT SUM(field) 部分蒂胞,和 selectMax() 方法一樣指蚜, 你可以使用第二個參數(shù)(可選)重命名結果字段猎提。

List<Record> list = DbHelper.create()
        .selectSum("age")
        .findAll("members");
// 執(zhí)行:SELECT SUM(`age`) AS `age`
// FROM `members`

from()

該方法用于編寫查詢語句中的 FROM 子句:

List<Record> list = DbHelper.create()
        .select("title, content, date")
        .from("mytable")
        .findAll();
// 執(zhí)行:SELECT `title`, `content`, `date`
// FROM `mytable`

注意:查詢中的 FROM 部分可以在方法 findAll() 中指定蚓炬,所以松逊,你可以 選擇任意一種你喜歡的方式。

join()

該方法用于編寫查詢語句中的 JOIN 子句:

List<Record> list = DbHelper.create()
        .select("*")
        .from("blogs")
        .join("comments", "comments.id=blogs.id")
        .findAll();
// 執(zhí)行:SELECT *
// FROM blogs
// JOIN comments ON comments.id=blogs.id

如果你的查詢中有多個連接肯夏,你可以多次調用這個方法经宏。

你可以傳入第三個參數(shù)指定連接的類型,有這樣幾種選擇:left驯击,right烁兰,outer,inner徊都,left outer 和 right outer 沪斟。

List<Record> list = DbHelper.create()
        .select("*")
        .from("blogs")
        .join("comments", "comments.id=blogs.id", "left")
        .findAll();
// 執(zhí)行:SELECT *
// FROM `blogs`
// LEFT JOIN `comments` ON `comments`.`id`=`blogs`.`id`

搜索[2]

where()

該方法提供了4中方式讓你編寫查詢語句中的 WHERE 子句:

注意:所有的數(shù)據(jù)將會自動轉義,生成安全的查詢語句暇矫。

  1. 簡單的 key/value 方式
List<Record> list = DbHelper.create()
       .where("name", "溫建寶")
       .findAll("mytable");
// 執(zhí)行:SELECT *
// FROM `mytable`
// WHERE `name` = '溫建寶'

注意自動為你加上了等號主之。

如果你多次調用該方法,那么多個 WHERE 條件將會使用 AND 連接起來:

List<Record> list = DbHelper.create()
        .where("name", "溫建寶")
        .where("title", "Java入門教程")
        .where("status", 1)
        .findAll("mytable");
// 執(zhí)行:SELECT *
// FROM `mytable`
// WHERE `name` = '溫建寶'
// AND `title` = 'Java入門教程'
// AND `status` = 1
  1. 自定義 key/value 方式

為了控制比較李根,你可以在第一個參數(shù)中包含一個比較運算符:

List<Record> list = DbHelper.create()
        .where("name !=", "溫建寶")
        .where("id <", 18)
        .findAll("mytable");
// 執(zhí)行:SELECT *
// FROM `mytable`
// WHERE `name` != '溫建寶'
// AND `id` < 18
  1. 關聯(lián)Map方式
Map<String, Object> where = new LinkedHashMap<>();
where.put("name", "溫建寶");
where.put("id", 18);
where.put("status", 2);

List<Record> list = DbHelper.create()
        .where(where)
        .findAll("mytable");
// 執(zhí)行:SELECT *
// FROM `mytable`
// WHERE `name` = '溫建寶'
// AND `id` = 18
// AND `status` = 2

你也可以在這個方法里包含你自己的比較運算符:

Map<String, Object> where = new LinkedHashMap<>();
where.put("name !=", "溫建寶");
where.put("id <", 18);
where.put("date >", "2019-03-09 12:45:03");

List<Record> list = DbHelper.create()
        .where(where)
        .findAll("mytable");
// 執(zhí)行:SELECT *
// FROM `mytable`
// WHERE `name` != '溫建寶'
// AND `id` < 18
// AND `date` > '2019-03-09 12:45:03'
  1. 自定義字符串

你可以完全手工編寫 WHERE 子句:

String where = "name='溫建寶' AND status=2 OR status=3";
List<Record> list = DbHelper.create()
        .where(where)
        .findAll("mytable");
// 執(zhí)行:
// SELECT *
// FROM `mytable`
// WHERE `name` = '溫建寶' AND `status` = 2 OR `status` = 3

注意:where() 方法有一個可選的第三個參數(shù)槽奕,如果設置為 false,sqlHelper 將不保護你的表名和字段名房轿。

List<Record> list = DbHelper.create()
        .where("mytable.name", "溫建寶", false)
        .findAll("mytable");
// 執(zhí)行:SELECT *
// FROM `mytable`
// WHERE mytable.name = 溫建寶

orWhere()

這個方法和上面的方法一樣粤攒,只是多個 WHERE 條件之間使用 OR 進行連接:

List<Record> list = DbHelper.create()
        .where("name !=", "溫建寶")
        .orWhere("id >", 18)
        .findAll("mytable");
// 執(zhí)行:SELECT *
// FROM `mytable`
// WHERE `name` != '溫建寶'
// OR `id` > 18

whereIn()

該方法用于生成 WHERE IN 子句,多個子句之間使用 AND 連接

List<Object> names = new ArrayList<>();
names.add("Frank");
names.add("Todd");
names.add("James");

List<Record> list = DbHelper.create()
        .whereIn("userName", names)
        .findAll("mytable");
// 執(zhí)行:SELECT *
// FROM `mytable`
// WHERE `userName` IN('Frank', 'Todd', 'James')

orWhereIn()

該方法用于生成 WHERE IN 子句囱持,多個子句之間使用 OR 連接

List<Object> names = new ArrayList<>();
names.add("Frank");
names.add("Todd");
names.add("James");

List<Record> list = DbHelper.create()
        .where("id>", 18)
        .orWhereIn("userName", names)
        .findAll("mytable");
// 執(zhí)行:SELECT *
// FROM `mytable`
// WHERE `id` > 18
// OR `userName` IN('Frank', 'Todd', 'James')

whereNotIn()

List<Object> names = new ArrayList<>();
names.add("Frank");
names.add("Todd");
names.add("James");

List<Record> list = DbHelper.create()
        .where("id>", 18)
        .whereNotIn("userName", names)
        .findAll("mytable");
// 執(zhí)行:SELECT *
// FROM `mytable`
// WHERE `id` > 18
// AND `userName` NOT IN('Frank', 'Todd', 'James')

orWhereNotIn()

該方法用于生成 WHERE NOT IN 子句夯接,多個子句之間使用 OR 連接

List<Object> names = new ArrayList<>();
names.add("Frank");
names.add("Todd");
names.add("James");

List<Record> list = DbHelper.create()
        .where("id>", 18)
        .orWhereNotIn("userName", names)
        .findAll("mytable");
// 執(zhí)行:SELECT *
// FROM `mytable`
// WHERE `id` > 18
// OR `userName` NOT IN('Frank', 'Todd', 'James')

模糊搜索[3]

like()

該方法用于生成 LIKE 子句,在進行搜索時非常有用纷妆。

注意:所有數(shù)據(jù)將會自動被轉義盔几。

  1. 簡單 key/value 方式
List<Record> list = DbHelper.create()
        .like("title", "match")
        .findAll("mytable");
// 執(zhí)行:SELECT *
// FROM `mytable`
// WHERE `title` LIKE '%match%' ESCAPE '!'

如果你多次調用該方法,那么多個 WHERE 條件將會使用 AND 連接起來:

List<Record> list = DbHelper.create()
        .like("title", "match")
        .like("body", "match")
        .findAll("mytable");
// 執(zhí)行:SELECT *
// FROM `mytable`
// WHERE `title` LIKE '%match%' ESCAPE '!'
// AND  `body` LIKE '%match%' ESCAPE '!'

可以傳入第三個可選的參數(shù)來控制 LIKE 通配符(%)的位置掩幢,可用選項有:'before'逊拍,'after' 和 'both'(默認為 'both')。

List<Record> list = DbHelper.create()
        .like("title", "match", "before")
        .findAll("mytable");
// 執(zhí)行:SELECT *
// FROM `mytable`
// WHERE `title` LIKE '%match' ESCAPE '!'

List<Record> list = DbHelper.create()
        .like("title", "match", "after")
        .findAll("mytable");
// 執(zhí)行:SELECT *
// FROM `mytable`
// WHERE `title` LIKE 'match%' ESCAPE '!'

List<Record> list = DbHelper.create()
        .like("title", "match", "both")
        .findAll("mytable");
// 執(zhí)行:SELECT *
// FROM `mytable`
// WHERE `title` LIKE '%match%' ESCAPE '!'
  1. 關聯(lián)Map方式
Map<String, String> likes = new LinkedHashMap<>();
likes.put("title", "match");
likes.put("page1", "match");
likes.put("page2", "match");

List<Record> list = DbHelper.create()
        .like(likes)
        .findAll("mytable");
    }
// 執(zhí)行:SELECT *
// FROM `mytable`
// WHERE `title` LIKE '%match%' ESCAPE '!'
// AND  `page1` LIKE '%match%' ESCAPE '!'
// AND  `page2` LIKE '%match%' ESCAPE '!'

orLike()

這個方法和上面的方法一樣粒蜈,只是多個 WHERE 條件之間使用 OR 進行連接:

List<Record> list = DbHelper.create()
        .like("title", "match")
        .orLike("body", "match")
        .findAll("mytable");
    }
// 執(zhí)行:SELECT *
// FROM `mytable`
// WHERE `title` LIKE '%match%' ESCAPE '!'
// OR  `body` LIKE '%match%' ESCAPE '!'

notLike()

這個方法和 like() 方法一樣顺献,只是生成 NOT LIKE 子句:

List<Record> list = DbHelper.create()
        .notLike("title", "match")
        .findAll("mytable");
// 執(zhí)行:SELECT *
// FROM `mytable`
// WHERE `title` NOT LIKE '%match%' ESCAPE '!'

orNotLike()

這個方法和 notLike() 方法一樣旗国,只是多個 WHERE 條件之間使用 OR 進行連接:

List<Record> list = DbHelper.create()
        .like("title", "match")
        .orNotLike("body", "match")
        .findAll("mytable");
// 執(zhí)行:SELECT *
// FROM `mytable`
// WHERE `title` LIKE '%match%' ESCAPE '!'
// OR  `body` NOT LIKE '%match%' ESCAPE '!'

groupBy()

該方法用于生成 GROUP BY 子句:

List<Record> list = DbHelper.create()
        .groupBy("title")
        .findAll("mytable");
// 執(zhí)行:SELECT *
// FROM `mytable`
// GROUP BY `title`

你也可以通過一個數(shù)組傳入多個值:

List<Record> list = DbHelper.create()
        .groupBy(new String[]{"title", "date"})
        .findAll("mytable");
// 執(zhí)行:SELECT *
// FROM `mytable`
// GROUP BY `title`, `date`

distinct()

該方法用于向查詢中添加 DISTINCT 關鍵字:

List<Record> list = DbHelper.create()
        .distinct()
        .findAll("mytable");
// 執(zhí)行:SELECT DISTINCT *
// FROM `mytable`

having()

該方法用于生成 HAVING 子句枯怖,有下面兩種不同的語法:

List<Record> list = DbHelper.create()
        .having("userId = 45")
        .findAll("mytable");
// 執(zhí)行:
// SELECT *
// FROM `mytable`
// HAVING `userId` = 45

List<Record> list = DbHelper.create()
        .having("userId", 45)
        .findAll("mytable");
// 執(zhí)行:SELECT *
// FROM `mytable`
// HAVING `userId` = 45

你也可以通過一個Map傳入多個值:

Map<String, Object> havings = new LinkedHashMap<>();
havings.put("title", "My Title");
havings.put("id <", 18);

List<Record> list = DbHelper.create()
        .having(havings)
        .findAll("mytable");
// 執(zhí)行:SELECT *
// FROM `mytable`
// HAVING `title` = 'My Title'
// AND `id` < 18

如果 sqlHelper 自動轉義你的查詢,為了避免轉義能曾,你可以將第三個參數(shù)設置為 false 度硝。

List<Record> list = DbHelper.create()
        .having("userId", 45)
        .findAll("mytable");
// 執(zhí)行:SELECT *
// FROM `mytable`
// HAVING `userId` = 45

List<Record> list = DbHelper.create()
        .having("userId", 45, false)
        .findAll("mytable");
// 執(zhí)行:SELECT *
// FROM `mytable`
// HAVING userId = 45

orHaving()

該方法和 having() 方法一樣肿轨,只是多個條件之間使用 OR 進行連接。

排序[4]

orderBy()

該方法用于生成 ORDER BY 子句蕊程。

第一個參數(shù)為你想要排序的字段名椒袍,第二個參數(shù)用于設置排序的方向, 可選項有: ASC(升序)藻茂,DESC(降序)和 RANDOM (隨機)驹暑。

List<Record> list = DbHelper.create()
        .orderBy("title", "desc")
        .findAll("mytable");
// 執(zhí)行:SELECT *
// FROM `mytable`
// ORDER BY `title` DESC

第一個參數(shù)也可以是你自己的排序字符串:

List<Record> list = DbHelper.create()
        .orderBy("title DESC, name ASC")
        .findAll("mytable");
// 執(zhí)行:SELECT *
// FROM `mytable`
// ORDER BY `title` DESC, `name` ASC

如果需要根據(jù)多個字段進行排序,可以多次調用該方法辨赐。

List<Record> list = DbHelper.create()
        .orderBy("title", "DESC")
        .orderBy("name", "ASC")
        .findAll("mytable");
// 執(zhí)行:SELECT *
// FROM `mytable`
// ORDER BY `title` DESC, `name` ASC

如果你選擇了 RANDOM (隨機排序)优俘,第一個參數(shù)會被忽略,但是你可以傳入一個 數(shù)字值掀序,作為隨機數(shù)的 seed帆焕。

List<Record> list = DbHelper.create()
        .orderBy("title", "RANDOM")
        .findAll("mytable");
// 執(zhí)行:SELECT *
// FROM `mytable`
// ORDER BY RAND()

List<Record> list = DbHelper.create()
        .orderBy(45, "RANDOM")
        .findAll("mytable");
    }
// 執(zhí)行:SELECT *
// FROM `mytable`
// ORDER BY RAND(45)

Oracle 暫時還不支持隨機排序,會默認使用升序

分頁與計數(shù)[5]

limit()

該方法用于限制你的查詢返回結果的數(shù)量:

List<Record> list = DbHelper.create()
        .limit(10)
        .findAll("mytable");
// 執(zhí)行:SELECT *
// FROM `mytable`
// LIMIT 10

輸入二個參數(shù)時不恭,第一個參數(shù)表示偏移叶雹,第二個參數(shù)表示返回數(shù)量限制。

List<Record> list = DbHelper.create()
        .limit(8, 10)
        .findAll("mytable");
// 執(zhí)行:SELECT *
// FROM `mytable`
// LIMIT 8, 10

offset()

跟 limit() 配合使用换吧,設置偏移量

List<Record> list = DbHelper.create()
        .limit(10)
        .offset(8)
        .findAll("mytable");
// 執(zhí)行:SELECT *
// FROM `mytable`
// LIMIT 8, 10

findCount()

該方法用于獲取特定查詢返回結果的數(shù)量折晦,也可以使用查詢構造器的這些方法: where(),orWhere()式散,like()筋遭,orLike() 等等。舉例:

int count = DbHelper.create()
        .where("age >", 18)
        .like("name", "match")
        .findCount("mytable");
// 執(zhí)行:SELECT COUNT(*) AS `numrows`
// FROM `mytable`
// WHERE `age` > 18
// AND  `name` LIKE '%match%' ESCAPE '!'

但是暴拄,這個方法會重置你在 select() 方法里設置的所有值漓滔,如果你希望保留它們,可以將 第二個參數(shù)設置為 false乖篷。

int count = DbHelper.create()
        .where("age >", 18)
        .like("name", "match")
        .findCount("mytable", false);

查詢條件組[6]

查詢條件組可以讓你生成用括號括起來的一組 WHERE 條件响驴,這能創(chuàng)造出非常復雜的 WHERE 子句, 支持嵌套的條件組撕蔼。例如:

List<Record> list = DbHelper.create()
        .select("*").from("my_table")
            .groupStart()
                .where("aa", "11")
                .orGroupStart()
                    .where("bb", "22")
                    .where("cc", "33")
                .groupEnd()
            .groupEnd()
            .where("dd", "44")
        .findAll();
// 執(zhí)行:SELECT *
// FROM `my_table`
// WHERE (
// `aa` = '11'
// OR  (
//         `bb` = '22'
//         AND `cc` = '33'
//     )
// )
// AND `dd` = '44'

注意:條件組必須要配對豁鲤,確保每個 groupStart() 方法都有一個 groupEnd() 方法與之配對。

groupStart()

開始一個新的條件組鲸沮,為查詢中的 WHERE 條件添加一個左括號琳骡。

orGroupStart()

開始一個新的條件組,為查詢中的 WHERE 條件添加一個左括號讼溺,并在前面加上 OR 楣号。

notGroupStart()

開始一個新的條件組,為查詢中的 WHERE 條件添加一個左括號,并在前面加上 NOT 炫狱。

orNotGroupStart()

開始一個新的條件組藻懒,為查詢中的 WHERE 條件添加一個左括號,并在前面加上 OR NOT 视译。

groupEnd()

結束當前的條件組嬉荆,為查詢中的 WHERE 條件添加一個右括號。

插入數(shù)據(jù)[7]

insert()

該方法根據(jù)你提供的數(shù)據(jù)生成一條 INSERT 語句并執(zhí)行酷含,它的參數(shù)是一個 Map對象鄙早,舉例:

Map<String, Object> data = new LinkedHashMap<>();
data.put("title", "My Title");
data.put("name", "My Name");
data.put("date", "My Date");

DbHelper.create().insert("mytable", data);
// 執(zhí)行:
// INSERT INTO `mytable` (`title`, `name`, `date`) VALUES ('My Title', 'My Name', 'My Date')

第一個參數(shù)為要插入的表名,第二個參數(shù)為要插入的數(shù)據(jù)椅亚,是個Map對象蝶锋。

注意:所有數(shù)據(jù)會被自動轉義,生成安全的查詢語句什往。

getCompiledInsert()

該方法和 insert() 方法一樣根據(jù)你提供的數(shù)據(jù)生成一條 INSERT 語句扳缕,但是并不執(zhí)行,舉例:

Map<String, Object> data = new LinkedHashMap<>();
data.put("title", "My Title");
data.put("name", "My Name");
data.put("date", "My Date");

String sql = DbHelper.create().set(data).getCompiledInsert("mytable");
System.out.println(sql);
// 輸出:
// INSERT INTO `mytable` (`title`, `name`, `date`) VALUES ('My Title', 'My Name', 'My Date')

第二個參數(shù)用于設置是否重置查詢(默認情況下會重置别威,正如 insert() 方法一樣):

DbHelper dbHelper = DbHelper.create();

String sql = dbHelper.set("title", "My Title").getCompiledInsert("mytable", false);
System.out.println(sql);
// 輸出:
// INSERT INTO `mytable` (`title`) VALUES ('My Title')

String sql2 = dbHelper.set("content", "My Content").getCompiledInsert();
System.out.println(sql2);
// 輸出:
// INSERT INTO `mytable` (`title`, `content`) VALUES ('My Title', 'My Content')

上面的例子中躯舔,最值得注意的是,第二個查詢并沒有用到 from() 方法省古, 也沒有為查詢指定表名參數(shù)粥庄,但是它生成的 SQL 語句中有 INTO mytable 子句。 這是因為查詢并沒有被重置(使用 insert() 方法會被執(zhí)行并被重置豺妓, 使用 resetQuery() 方法直接重置)惜互。

注意:這個方法不支持批量插入。

insertBatch()

該方法根據(jù)你提供的數(shù)據(jù)生成一條 INSERT 語句并執(zhí)行琳拭,它的參數(shù)是一個 數(shù)組训堆,舉例:

List<Map<String, Object>> data = new ArrayList<>();

Map<String, Object> item = new HashMap<>();
item.put("title", "My title");
item.put("name", "My Name");
item.put("date", "My date");
data.add(item);

Map<String, Object> item2 = new HashMap<>();
item2.put("title", "Another title");
item2.put("name", "Another Name");
item2.put("date", "Another date");
data.add(item2);

DbHelper.create().insertBatch("mytable", data);

// 執(zhí)行:
// INSERT INTO `mytable` (`date`, `name`, `title`) VALUES ('My date','My Name','My title'), ('Another date','Another Name','Another title')

第一個參數(shù)為要插入的表名,第二個參數(shù)為要插入的數(shù)據(jù)白嘁。

所有數(shù)據(jù)會被自動轉義坑鱼,生成安全的查詢語句。

更新數(shù)據(jù)[8]

replace()

該方法用于執(zhí)行一條 REPLACE 語句絮缅,REPLACE 語句根據(jù)表的【主鍵】和【唯一索引】來執(zhí)行鲁沥,類似于標準的 DELETE + INSERT 。 使用這個方法耕魄,你不用再手工去實現(xiàn) select()画恰,update(),delete() 以及 insert() 這些方法的不同組合吸奴,為你節(jié)約大量時間允扇。

例如:

Map<String, Object> data = new HashMap<>();
data.put("title", "My title");
data.put("name", "My Name");
data.put("date", "My date");

DbHelper.create().replace("mytable", data);
// 執(zhí)行:
// REPLACE INTO `mytable` (`date`, `name`, `title`) VALUES ('My date', 'My Name', 'My title')

上面的例子中马靠,我們假設 title 字段是我們的主鍵,那么如果我們數(shù)據(jù)庫里有一行 的 title 列的值為 'My title'蔼两,這一行將會被刪除并被我們的新數(shù)據(jù)所取代。

也可以使用 set() 方法逞度,而且所有字段都被自動轉義额划,正如 insert() 方法一樣。

set()

該方法用于設置新增或更新的數(shù)據(jù)档泽。

該方法可以取代直接傳遞數(shù)據(jù)Map到 insert() 或 update() 方法:

DbHelper.create()
        .set("name", "溫建寶")
        .insert("mytable");
// 執(zhí)行:
// INSERT INTO `mytable` (`name`) VALUES ('溫建寶')

如果你多次調用該方法俊戳,它會正確組裝出 INSERT 或 UPDATE 語句來:

DbHelper.create()
        .set("name", "溫建寶")
        .set("title", "Java入門教程")
        .set("status", 2)
        .insert("mytable");
// 執(zhí)行:
// INSERT INTO `mytable` (`name`, `title`, `status`) VALUES ('溫建寶', 'Java入門教程', 2)

set() 方法也接受可選的第三個參數(shù)(escape),如果設置為 false馆匿,數(shù)據(jù)將不會自動轉義抑胎。為了說明兩者之間的區(qū)別,這里有一個帶轉義的 set() 方法和不帶轉義的例子渐北。

DbHelper.create()
        .set("field", "field+1", false)
        .set("id", 9)
        .insert("mytable");
// 執(zhí)行:
// INSERT INTO `mytable` (field, `id`) VALUES (field+1, 9)

DbHelper.create()
        .set("field", "field+1")
        .set("id", 9)
        .insert("mytable");
// 執(zhí)行:
// INSERT INTO `mytable` (`field`, `id`) VALUES ('field+1', 9)

你也可以傳一個關聯(lián)Map對象作為參數(shù):

Map<String, Object> data = new LinkedHashMap<>();
data.put("name", "溫建寶");
data.put("title", "Java入門教程");
data.put("status", 9);

DbHelper.create()
        .set(data)
        .insert("mytable");
// 執(zhí)行:
// INSERT INTO `mytable` (`name`, `title`, `status`) VALUES ('溫建寶', 'Java入門教程', 9)

update()

該方法根據(jù)你提供的數(shù)據(jù)生成一條 UPDATE 語句并執(zhí)行阿逃,它的參數(shù)是一個 Map對象 ,舉例:

Map<String, Object> data = new LinkedHashMap<>();
data.put("name", "溫建寶");
data.put("title", "Java入門教程");
data.put("date", "2019-03-10");

DbHelper.create()
        .where("id", 20)
        .update("mytable", data);
// 執(zhí)行:
// UPDATE `mytable` SET `name` = '溫建寶', `title` = 'Java入門教程', `date` = '2019-03-10'
// WHERE `id` = 20

所有數(shù)據(jù)會被自動轉義赃蛛,生成安全的查詢語句恃锉。

你應該注意到 where() 方法的使用,它可以為你設置 WHERE 子句呕臂。 你也可以直接使用字符串形式設置 WHERE 子句:

Map<String, Object> data = new LinkedHashMap<>();
data.put("name", "溫建寶");
data.put("title", "Java入門教程");
data.put("date", "2019-03-10");

DbHelper.create()
        .update("mytable", data, "id=20");
// 執(zhí)行:
// UPDATE `mytable` SET `name` = '溫建寶', `title` = 'Java入門教程', `date` = '2019-03-10'
// WHERE `id` = 20

或者使用一個Map對象:

Map<String, Object> data = new LinkedHashMap<>();
data.put("name", "溫建寶");
data.put("title", "Java入門教程");
data.put("date", "2019-03-10");

Map<String, Object> where = new LinkedHashMap<>();
where.put("id", 4);

DbHelper.create()
        .update("mytable", data, where);
// 執(zhí)行:
// UPDATE `mytable` SET `name` = '溫建寶', `title` = 'Java入門教程', `date` = '2019-03-10'
// WHERE `id` = 4

當執(zhí)行 UPDATE 操作時破托,你還可以使用上面介紹的 set() 方法。

updateBatch()

該方法根據(jù)你提供的數(shù)據(jù)生成一條 UPDATE 語句并執(zhí)行歧蒋,它的參數(shù)是一個數(shù)組土砂,舉例:

List<Map<String, Object>> data = new ArrayList<>();

Map<String, Object> set = new HashMap<>();
set.put("title", "My Title");
set.put("name", "My Name");
set.put("date", "My Date");
data.add(set);

Map<String, Object> set2 = new HashMap<>();
set2.put("title", "My Title2");
set2.put("name", "My Name2");
set2.put("date", "My Date2");
data.add(set2);

DbHelper.create()
        .updateBatch("mytable", data, "title");
// 執(zhí)行:
// UPDATE `mytable` SET `date` = CASE 
// WHEN `title` = 'My Title' THEN 'My Date'
// WHEN `title` = 'My Title2' THEN 'My Date2'
// ELSE`date` END, `name` = CASE 
// WHEN `title` = 'My Title' THEN 'My Name'
// WHEN `title` = 'My Title2' THEN 'My Name2'
// ELSE`name` END, 
// WHERE `title` IN('My Title', 'My Title2')

第一個參數(shù)為要更新的表名,第二個參數(shù)為要更新的數(shù)據(jù)谜洽,是個Map對象數(shù)組萝映,第三個 參數(shù)是 WHERE 語句的鍵。

所有數(shù)據(jù)會被自動轉義阐虚,生成安全的查詢語句锌俱。

getCompiledUpdate()

該方法和 getCompiledInsert() 方法完全一樣,除了生成的 SQL 語句是 UPDATE 而不是 INSERT敌呈。

該方法不支持批量更新贸宏。

刪除數(shù)據(jù)[9]

delete()

該方法生成 DELETE 語句并執(zhí)行。

Map<String, Object> where = new HashMap<>();
where.put("id", 9);

DbHelper.create()
        .delete("mytable", where);
// 執(zhí)行:
// DELETE FROM `mytable`
// WHERE `id` = 9

第一個參數(shù)為表名磕洪,第二個參數(shù)為 WHERE 條件吭练。你也可以不用第二個參數(shù), 使用 where() 或者 orWhere() 函數(shù)來替代它:

DbHelper.create()
        .where("id", 9)
        .delete("mytable");
// 執(zhí)行:
// DELETE FROM `mytable`
// WHERE `id` = 9

如果你想要刪除一個表中的所有數(shù)據(jù)析显,可以使用 truncate() 或 emptyTable() 方法鲫咽。

emptyTable()

該方法生成 DELETE 語句并執(zhí)行:

DbHelper.create()
        .emptyTable("mytable");
// 執(zhí)行:
// DELETE FROM `mytable`

truncate()

該方法生成 TRUNCATE 語句并執(zhí)行。

DbHelper.create()
        .truncate("mytable");
// 或
DbHelper.create()
        .from("mytable")
        .truncate();

// 執(zhí)行:
// TRUNCATE `mytable`

getCompiledDelete()

該方法和 getCompiledInsert() 方法完全一樣,除了生成的 SQL 語句是 DELETE 而不是 INSERT分尸。

鏈式方法[10]

通過將多個方法連接在一起锦聊,鏈式方法可以大大的簡化你的語法。感受一下這個例子:

DbHelper.create()
        .select("title")
        .where("id", 20)
        .findAll("mytable");

查詢構造器緩存[11]

盡管不是 "真正的" 緩存箩绍,查詢構造器允許你將查詢的某個特定部分保存(或 "緩存")起來孔庭, 以便在你的腳本執(zhí)行之后重用。一般情況下材蛛,當查詢構造器的一次調用結束后圆到,所有已存儲的信息 都會被重置,以便下一次調用卑吭。如果開啟緩存芽淡,你就可以使信息避免被重置,方便你進行重用豆赏。

緩存調用是累加的挣菲。如果你調用了兩次有緩存的 select(),然后再調用兩次沒有緩存的 select()掷邦, 這會導致 select() 被調用4次己单。

有三個可用的緩存方法方法:

startCache()

如需開啟緩存必須先調用此方法,所有支持的查詢類型(見下文)都會被存儲起來供以后使用耙饰。

stopCache()

此方法用于停止緩存纹笼。

flushCache()

此方法用于清空緩存。

這里是一個使用緩存的例子:

DbHelper dbHelper = DbHelper.create();

dbHelper.startCache()
.select("field1")
.stopCache()
.findAll("mytable");
// 執(zhí)行:
// SELECT `field1`
// FROM `mytable`

dbHelper.select("field2").findAll("mytable");
// 執(zhí)行:
// SELECT `field1`, `field2` FROM (`mytable`)

dbHelper.flushCache()
        .select("field2")
        .findAll("mytable");
// 執(zhí)行:
// SELECT `field2` FROM (`mytable`)

支持緩存的語句有: select, from, join, where, like, groupBy, having, orderBy

重置查詢構造器[12]

resetQuery()

該方法無需執(zhí)行就能重置查詢構造器中的查詢苟跪,findAll() 和 insert() 方法也可以用于重置查詢廷痘,但是必須要先執(zhí)行它。和這兩個方法一樣件已,使用查詢構造器緩存_ 緩存下來的查詢不會被重置笋额。

當你在使用查詢構造器生成 SQL 語句(如:getCompiledSelect()),之后再執(zhí)行它篷扩。這種情況下兄猩,不重置查詢緩存將非常有用:

DbHelper dbHelper = DbHelper.create();

dbHelper.select("field1, field2")
        .where("field3", 5)
        .getCompiledSelect("mytable", false);

List<Record> list = dbHelper.findAll();
// 執(zhí)行:
// SELECT field1, field1 from mytable where field3 = 5;

如果你正在使用查詢構造器緩存功能,連續(xù)兩次調用 getCompiledSelect() 方法 并且不重置你的查詢鉴未,這將會導致緩存被合并兩次枢冤。舉例來說,例如你正在緩存 select() 方法铜秆,那么會查詢兩個相同的字段淹真。

對JFinal DB API 簡單封裝[13]

DbHelper.java : 繼承了SqlHelper類,擁有構造SQL字符串的能力连茧,同時簡單封裝了JFinal框架執(zhí)行SQL語句的API核蘸,讓自己又有執(zhí)行SQL語句的能力巍糯。

create()

返回 DbHelper 新實例,同時可傳入 configName 參數(shù)客扎,自由切換 數(shù)據(jù)庫的連接祟峦,舉例:

DbHelper dbHelper = DbHelper.create("mysql_pro");

findAll()

返回 所有的 查詢記錄,舉例:

List<Record> list = DbHelper.create()
        .from("blog")
        .where("userName", "溫建寶")
        .findAll();
// 執(zhí)行:
// SELECT *
// FROM `blog`
// WHERE `userName` = '溫建寶'

findFirst()

返回 一條 查詢記錄徙鱼,舉例:

Record record = DbHelper.create()
        .from("blog")
        .where("userName", "溫建寶")
        .findFirst();
// 執(zhí)行:
// SELECT *
// FROM `blog`
// WHERE `userName` = '溫建寶'
// LIMIT 1

findCount()

返回 滿足查詢條件的記錄數(shù)宅楞,舉例:

int count = DbHelper.create()
        .from("blog")
        .where("userName", "溫建寶")
        .findCount();
// 執(zhí)行:
// SELECT COUNT(*) AS `numrows`
// FROM `blog`
// WHERE `userName` = '溫建寶'

findPage()

查詢分頁

Page<Record> page = DbHelper.create()
        .from("blog")
        .where("userName", "溫建寶")
        .findPage(2, 10);

對JFinal Model API 簡單封裝[14]

ModelHelper.java : 繼承了SqlHelper類,擁有構造SQL字符串的能力疆偿,同時傳入 模型實例,讓自己又有執(zhí)行SQL語句的能力搓幌。

/**
 * 模型 助手類
 *
 * @author php-note.com
 */
@SuppressWarnings({"serial"})
public class ModelHelper<M extends Model<M>> extends SqlHelper<ModelHelper<M>> {
    private M dao;    // 模型實例杆故,專門用來執(zhí)行SQL的

    /**
     * 構造方法
     *
     * @param dao 模型實例
     */
    public ModelHelper(M dao) {
        this.dao = dao;
    }
    
    // 省略代碼。溉愁。处铛。
}

假如有一個模型:Blog.java

/**
 * Generated by JFinal.
 */
@SuppressWarnings("serial")
public class Blog extends BaseBlog<Blog> {
    public static       String tableName = "blog";
    public static final Blog   dao       = new Blog().dao();

    // 省略代碼。拐揭。撤蟆。
}

findAll()

返回 所有的 查詢記錄,舉例:

List<Blog> blogList = new ModelHelper<>(Blog.dao)
        .from(Blog.tableName)
        .where("blogId >", 2)
        .findAll();

findFirst()

返回 一條 查詢記錄堂污,舉例:

Blog blog = new ModelHelper<>(Blog.dao)
        .from(Blog.tableName)
        .where("blogId", 2)
        .findFirst();

findPage()

查詢分頁

Page<Blog> page = new ModelHelper<>(Blog.dao)
        .from(Blog.tableName)
        .where("blogId >", 2)
        .findPage(1, 20);

項目地址:Github


  1. 查詢 ?

  2. 搜索 ?

  3. 模糊搜索 ?

  4. 排序 ?

  5. 分頁與計數(shù) ?

  6. 查詢條件組 ?

  7. 插入數(shù)據(jù) ?

  8. 更新數(shù)據(jù) ?

  9. 刪除數(shù)據(jù) ?

  10. 鏈式方法 ?

  11. 查詢構造器緩存 ?

  12. 重置查詢構造器 ?

  13. 對JFinal DB API 簡單封裝 ?

  14. 對JFinal Model API 簡單封裝 ?

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末家肯,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子盟猖,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,036評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件浓领,死亡現(xiàn)場離奇詭異犯戏,居然都是意外死亡,警方通過查閱死者的電腦和手機娘汞,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評論 3 395
  • 文/潘曉璐 我一進店門歹茶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人你弦,你說我怎么就攤上這事惊豺。” “怎么了禽作?”我有些...
    開封第一講書人閱讀 164,411評論 0 354
  • 文/不壞的土叔 我叫張陵扮叨,是天一觀的道長。 經常有香客問我领迈,道長彻磁,這世上最難降的妖魔是什么碍沐? 我笑而不...
    開封第一講書人閱讀 58,622評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮衷蜓,結果婚禮上累提,老公的妹妹穿的比我還像新娘。我一直安慰自己磁浇,他們只是感情好斋陪,可當我...
    茶點故事閱讀 67,661評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著置吓,像睡著了一般无虚。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上衍锚,一...
    開封第一講書人閱讀 51,521評論 1 304
  • 那天友题,我揣著相機與錄音,去河邊找鬼戴质。 笑死度宦,一個胖子當著我的面吹牛,可吹牛的內容都是我干的告匠。 我是一名探鬼主播戈抄,決...
    沈念sama閱讀 40,288評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼后专!你這毒婦竟也來了划鸽?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,200評論 0 276
  • 序言:老撾萬榮一對情侶失蹤戚哎,失蹤者是張志新(化名)和其女友劉穎漾稀,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體建瘫,經...
    沈念sama閱讀 45,644評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡崭捍,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,837評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了啰脚。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片殷蛇。...
    茶點故事閱讀 39,953評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖橄浓,靈堂內的尸體忽然破棺而出粒梦,到底是詐尸還是另有隱情,我是刑警寧澤荸实,帶...
    沈念sama閱讀 35,673評論 5 346
  • 正文 年R本政府宣布匀们,位于F島的核電站,受9級特大地震影響准给,放射性物質發(fā)生泄漏泄朴。R本人自食惡果不足惜重抖,卻給世界環(huán)境...
    茶點故事閱讀 41,281評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望祖灰。 院中可真熱鬧钟沛,春花似錦、人聲如沸局扶。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,889評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽三妈。三九已至畜埋,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間畴蒲,已是汗流浹背悠鞍。 一陣腳步聲響...
    開封第一講書人閱讀 33,011評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留饿凛,地道東北人狞玛。 一個月前我還...
    沈念sama閱讀 48,119評論 3 370
  • 正文 我出身青樓软驰,卻偏偏與公主長得像涧窒,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子锭亏,可洞房花燭夜當晚...
    茶點故事閱讀 44,901評論 2 355

推薦閱讀更多精彩內容