新聞中心
接觸一個(gè)新工具的時(shí)候,剛開始要克服的***障礙就是如何讓你自己先嘗試做出一個(gè)小東西來(lái)。現(xiàn)在你也許對(duì) Java 8 中新的 Stream API 的運(yùn)作方式在理解上比較自信,但你也許并沒(méi)用它來(lái)進(jìn)行過(guò)數(shù)據(jù)庫(kù)查詢操作。為了幫助你開始使用 Stream API 來(lái)對(duì) SQL 數(shù)據(jù)庫(kù)進(jìn)行創(chuàng)建、修改和讀取操作, 我已經(jīng)在這個(gè)快速開始的教程中把它們整合到了一起。希望它能幫助你提升對(duì)流式API的使用水平!

目前創(chuàng)新互聯(lián)已為近千家的企業(yè)提供了網(wǎng)站建設(shè)、域名、虛擬空間、成都網(wǎng)站托管、企業(yè)網(wǎng)站設(shè)計(jì)、連云港網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長(zhǎng),共同發(fā)展。
背景
Speedment 是一個(gè)開放源代碼的工具集,它可以被用來(lái)生成 Java 實(shí)體,并且能將我們同數(shù)據(jù)庫(kù)的通信過(guò)程管理起來(lái)。你可以利用一個(gè)圖形工具連接到數(shù)據(jù)庫(kù)并生成出一套完整的 ORM 框架代碼來(lái)表示域模型。但是 Speedment 不單單只是一個(gè)代碼生成器而已,它還是一個(gè)能插入應(yīng)用程序中的運(yùn)行時(shí)程序,這樣就有可能將你的 Java 8 流式代碼翻譯成優(yōu)化過(guò)的SQL查詢。這也是我將會(huì)在本文中專門講述的一個(gè)部分。
生成代碼
要在一個(gè) Maven 工程中開始使用 Speedment,需要你將下面幾行代碼添加到你的 pom.xml 文件中。在本例中,我使用的是 MySQL,而你也可以選擇使用 PostgreSQL 或者 MariaDB。面向于像Oracle這樣的專有數(shù)據(jù)庫(kù)可用于企業(yè)級(jí)客戶。
Pom.xml
3.0.1 mysql mysql-connector-java 5.1.39 com.speedment runtime ${speedment.version} pom ${db.groupId} ${db.artifactId} ${db.version} com.speedment speedment-maven-plugin ${speedment.version} ${db.groupId} ${db.artifactId} ${db.version}
現(xiàn)在你可以訪問(wèn)到許多新的 Maven 資源庫(kù),它們能讓你更加輕松的使用這個(gè)工具包。要啟動(dòng) Speedment UI, 執(zhí)行如下命令:
- mvn speedment:tool
這樣就會(huì)有一個(gè)過(guò)程引導(dǎo)你連接到數(shù)據(jù)庫(kù)并對(duì)代碼生成進(jìn)行配置。一開始最簡(jiǎn)單的方法就是用默認(rèn)的設(shè)置先跑起來(lái)再說(shuō)。當(dāng)你按下生成按鈕“Generate,” Speedment 就會(huì)對(duì)你的數(shù)據(jù)庫(kù)元數(shù)據(jù)進(jìn)行分析,然后在你的工程中添加像實(shí)體和實(shí)體管理器這樣的類。
初始化 Speedment
當(dāng)你的域模型生成好了以后,Speedment 的設(shè)置就容易了。創(chuàng)建一個(gè)新的 Main.java 文件然后添加如下幾行代碼。你看到的類都是生成的,因此它們的命名都是根據(jù)數(shù)據(jù)庫(kù)模式、表以及列的名稱來(lái)決定的。
Main.java
- public class Main {
- public static void main(String... param) {
- final HaresApplication app = new HaresApplicationBuilder()
- .withPassword("password")
- .build();
- }
- }
上面的代碼創(chuàng)建了一個(gè)新的應(yīng)用程序?qū)嶓w,它使用了一種生成的構(gòu)造器模式。構(gòu)造器是的對(duì)任何運(yùn)行時(shí)配置細(xì)節(jié)的設(shè)置成為可能,例如數(shù)據(jù)庫(kù)的密碼。
當(dāng)我們有了一個(gè)應(yīng)用實(shí)體,就可以用它來(lái)訪問(wèn)生成的實(shí)體管理器了。在這里,我的數(shù)據(jù)庫(kù)中有了四個(gè)表; “hare”, “carrot”, “human”, 以及 “friend”. (你可以在這里找到完整的數(shù)據(jù)庫(kù)定義)。
- final CarrotManager carrots = app.getOrThrow(CarrotManager.class);
- final HareManager hares = app.getOrThrow(HareManager.class);
- final HumanManager humans = app.getOrThrow(HumanManager.class);
- final FriendManager hares = app.getOrThrow(FriendManager.class);
現(xiàn)在這些實(shí)體管理器可以被用來(lái)執(zhí)行所有的CRUD操作了。
創(chuàng)建實(shí)體
創(chuàng)建實(shí)體的方式非常直接。我們就使用實(shí)體生成的實(shí)現(xiàn),把列的值設(shè)置好然后持久化到數(shù)據(jù)源就可以了。
- hares.persist(
- new HareImpl()
- .setName("Harry")
- .setColor("Gray")
- .setAge(8)
- );
persist 方法會(huì)返回一個(gè) (潛在的) Hare 新實(shí)例,里面像“id”這種自動(dòng)生成鍵已經(jīng)設(shè)置好了。如果我們想在持久化之后繼續(xù)使用 Harry, 那就可以使用 persist 方法返回的這個(gè):
- final Hare harry = hares.persist(
- new HareImpl()
- .setName("Harry")
- .setColor("Gray")
- .setAge(8)
- );
如果持久化操作失敗了,例如如果有一個(gè)外鍵違反了唯一性約束,就會(huì)有一個(gè) SpeedmentException 拋出。我們應(yīng)該對(duì)此進(jìn)行檢查,如果有默寫東西會(huì)阻止我們對(duì)這條 hare 記錄進(jìn)行持久化,就應(yīng)該顯示一條錯(cuò)誤信息。
- try {
- final Hare harry = hares.persist(
- new HareImpl()
- .setName("Harry")
- .setColor("Gray")
- .setAge(8)
- );
- } catch (final SpeedmentException ex) {
- System.err.println(ex.getMessage());
- return;
- }
讀取實(shí)體
Speedment 運(yùn)行時(shí)中最酷的功能特性就是能夠使用 Java 8 的 Stream API對(duì)數(shù)據(jù)庫(kù)中的數(shù)據(jù)進(jìn)行流式操作。“為什么這樣做會(huì)很酷呢?” 你可能會(huì)這樣問(wèn)你自己?!叭缃裆踔罤ibernate 都已經(jīng)支持流式操作了!”這就是回答。
使用 Speedment 流式操作最美好的事情就是它們把構(gòu)建流的中間和終止動(dòng)作都考慮進(jìn)去了。這就意味著如果你在流已經(jīng)被創(chuàng)建之后添加一個(gè)過(guò)濾器進(jìn)去,那么在構(gòu)建 SQL 語(yǔ)句時(shí)這個(gè)過(guò)濾器也會(huì)被考慮進(jìn)去。
下面是一個(gè)示例,我們想要計(jì)算數(shù)據(jù)庫(kù)中 hare 記錄的總數(shù)。
- final long haresTotal = hares.stream().count();
- System.out.format("There are %d hares in total.%n", haresTotal);
這段代碼將會(huì)生成的SQL查詢?nèi)缦拢?/p>
- SELECT COUNT(id) FROM hares.hare;
這里的終止操作就是 .count() ,因此 Speedment 就知道是要?jiǎng)?chuàng)建一個(gè) SELECT COUNT(…) 語(yǔ)句。它也知道 “hare”表的主鍵是“id”這個(gè)列,如此就有可能將發(fā)送給數(shù)據(jù)庫(kù)的整個(gè)語(yǔ)句 減少到這個(gè)樣子。
更加復(fù)雜的示例可能就是找出名稱以 “rry” 并且年齡大于等于 5 的兔子的數(shù)量。這個(gè)可以這樣寫:
- final long complexTotal = hares.stream()
- .filter(Hare.NAME.endsWith("rry"))
- .filter(Hare.AGE.greaterOrEqual(5))
- .count();
我們使用由 Speedment 為我們生成的位于構(gòu)建器來(lái)定義過(guò)濾器。這使得我們以編程的方式對(duì)流進(jìn)行分析并且將其簡(jiǎn)化到如下這樣一條SQL語(yǔ)句成為可能:
- SELECT COUNT(id) FROM hares.hare
- WHERE hare.name LIKE CONCAT("%", ?)
- AND hare.age >= 5;
如果我們添加了一個(gè) Speedment 不可以對(duì)流進(jìn)行優(yōu)化的操作, 它就會(huì)像一般的 Java 8 流那被處理。我們永遠(yuǎn)都不會(huì)限制生成的位于構(gòu)建器的使用,它能是流式操作更加的高效。
- final long inefficientTotal = hares.stream()
- .filter(h -> h.getName().hashCode() == 52)
- .count();
上述代碼會(huì)產(chǎn)生一條如下極其低效的語(yǔ)句,但是它仍然可以跑起來(lái)。
- SELECT id,name,color,age FROM hares.hare;
更新實(shí)體
更新存在的實(shí)體和讀取以及持久化實(shí)體非常相似。在我們調(diào)用update()方法之前,對(duì)實(shí)體本地拷貝的改變,不會(huì)影響數(shù)據(jù)庫(kù)內(nèi)容。
下面,我們拿到之前使用Hare創(chuàng)建的Harry,并將他的顏色變?yōu)樽厣?/p>
- harry.setColor("brown");
- final Hare updatedHarry = hares.update(harry);
如果更新被接受了,那么管理器會(huì)返回hare的一個(gè)新的拷貝,因?yàn)槲覀冊(cè)诤竺鏁?huì)繼續(xù)使用這個(gè)實(shí)例。就想做“創(chuàng)建”的例子中,更新可能會(huì)失敗。也許顏色被定義為“值唯一”,棕色已經(jīng)存在于hare中。那樣的話,會(huì)拋出一個(gè)SpeedmentException異常.
我們也可以通過(guò)合并多個(gè)實(shí)體到一個(gè)流中來(lái)同時(shí)更新他們。加入我們想將所有名字為Harry的hare變?yōu)樽厣覀兛梢赃@樣做:
- hares.stream()
- .filter(Hare.NAME.equal("Harry"))
- .map(Hare.COLOR.setTo("Brown"))
- .forEach(hares.updater()); // 更新流中存在的元素
我們還應(yīng)該使用try-catch語(yǔ)句來(lái)確保在運(yùn)行過(guò)程中有失敗發(fā)生時(shí)警告用戶。
- try {
- hares.stream()
- .filter(Hare.NAME.equal("Harry"))
- .map(Hare.COLOR.setTo("Brown"))
- .forEach(hares.updater());
- } catch (final SpeedmentException ex) {
- System.err.println(ex.getMessage());
- return;
- }
實(shí)體刪除
我們需要知道的***一個(gè) CRUD 操作就是從數(shù)據(jù)庫(kù)中刪除實(shí)體。這個(gè)操作幾乎和“更新”操作時(shí)等同的。假如說(shuō)我們要把年齡超過(guò)10歲的兔子的記錄都刪除,就要這樣做:
- try {
- hares.stream()
- .filter(Hare.AGE.greaterThan(10))
- .forEach(hares.remover()); // Removes remaining hares
- } catch (final SpeedmentException ex) {
- System.err.println(ex.getMessage());
- return;
- }
總結(jié)
通過(guò)閱讀本文你已經(jīng)了解了如何在一個(gè) Maven 工程中對(duì) Speedment 進(jìn)行設(shè)置,還有如何使用 Java 8 的 Stream API 來(lái)從數(shù)據(jù)庫(kù)中創(chuàng)建、更新、讀取以及刪除實(shí)體。這是你可以利用 Speedment 所能進(jìn)行的操作的一個(gè)小的子集, 但已經(jīng)是一個(gè)能讓你上手的好的開始了。更多的示例以及更加高級(jí)的使用場(chǎng)景可以在GitHub-page上找到。
網(wǎng)頁(yè)題目:Java8Streams中的數(shù)據(jù)庫(kù)CRUD操作
文章出自:http://m.fisionsoft.com.cn/article/cccjcop.html


咨詢
建站咨詢
