将jOOQ与JDBC比较
本文是我們學(xué)院課程的一部分,標題為jOOQ –類型安全的數(shù)據(jù)庫查詢 。
在SQL和特定關(guān)系數(shù)據(jù)庫很重要的Java應(yīng)用程序中,jOOQ是一個不錯的選擇。 當JPA / Hibernate抽象過多,JDBC過多時,這是一種替代方法。 它顯示了一種現(xiàn)代的領(lǐng)域特定語言如何可以極大地提高開發(fā)人員的生產(chǎn)率,從而將SQL內(nèi)部化為Java。
在本課程中,我們將看到如何使用jOOQ有效地查詢數(shù)據(jù)庫。 在這里查看 !
目錄
1.簡介 2.檢查異常1.簡介
也可以從org.jooq.academy.section3包中獲得本節(jié)中顯示的示例 。
大多數(shù)Java開發(fā)人員對JDBC是什么以及它如何工作都有深刻的了解。 如果還沒有的話,請查看Oracle的官方JDBC教程以了解有關(guān)JDBC的更多信息。
JDBC通常因冗長而受到批評。 JDBC也因選擇了錯誤的“默認值”而受到批評,例如,默認的結(jié)果集的延遲實現(xiàn)。 我們將看到j(luò)OOQ如何改進這些批評:
2.檢查異常
Java的檢查異常已被視為失敗,這也是Java 8的新Streams API和所有相關(guān)功能接口不再支持檢查異常的原因。
jOOQ的所有API都將拋出從jOOQ的org.jooq.exception.DataAccessException派生的RuntimeExceptions ,在大多數(shù)情況下您無需捕獲它,從而使其中止當前的正在運行的事務(wù)。 比較兩者的示例:
JDBC
// These two calls can throw a SQLException try (PreparedStatement stmt = connection.prepareStatement("SELECT FIRST_NAME FROM AUTHOR");ResultSet rs = stmt.executeQuery()) {// This can throw a SQLExceptionwhile (rs.next()) {// This can throw a SQLExceptionSystem.out.println(rs.getString(1));} }OO
DSL.using(connection).select(AUTHOR.FIRST_NAME).from(AUTHOR).fetch().forEach(record -> System.out.println(record.getValue(AUTHOR.FIRST_NAME)));3.結(jié)果集
JDBC的ResultSet是一個非常有狀態(tài)的對象,無法與Java collections API很好地互操作。 例如,它沒有實現(xiàn)Iterator ,因為它還必須適應(yīng)在基礎(chǔ)數(shù)據(jù)庫游標中向后滾動-幾乎任何人都不需要的功能。
jOOQ通過org.jooq.Result類型更好地集成了SQL結(jié)果集,可容納所有用例的95%:
- jOOQ的Result實現(xiàn)了java.util.List ,因此繼承了List的所有功能,包括將其轉(zhuǎn)換為Java 8 Stream的功能 。
- jOOQ的Result已完全實現(xiàn)到Java內(nèi)存中,而不是默認情況下是惰性的。 這樣可以盡早釋放資源。
- jOOQ的Result知道其自己的Record類型,該類型允許通過列引用而不是列索引進行類型安全的訪問記錄屬性。
請注意,以上是默認設(shè)置。 如果您有較大的結(jié)果集,并且不想逐條記錄地實現(xiàn),則可以始終使用jOOQ的惰性獲取功能。 在以下示例中可以看出:
您可以在foreach循環(huán)中使用jOOQ結(jié)果
for (Record record : DSL.using(connection).select().from(AUTHOR).fetch()) {System.out.println(record); }您可以將jOOQ結(jié)果與Java 8流一起使用
DSL.using(connection).select().from(AUTHOR).fetch().stream().flatMap(record -> Arrays.stream(record.intoArray())).forEach(System.out::println);4.準備的陳述
奇怪的是,JDBC區(qū)分靜態(tài)java.sql.Statement類型和java.sql.PreparedStatement類型。 這種做法將使您不必執(zhí)行往返數(shù)據(jù)庫的操作即可在執(zhí)行之前準備語句-但是,無論如何,最好使用準備好的語句來執(zhí)行所有查詢的95%,所以為什么要打擾呢?
jOOQ不會通過單獨的語句類型來區(qū)分這兩種執(zhí)行模式 。 相反,您可以使用設(shè)置標志來指示在真正需要時應(yīng)執(zhí)行靜態(tài)語句。 一個例子:
JDBC
// Static statement try (Statement stmt = connection.createStatement()) {// Remember to pass the SQL string here!stmt.executeUpdate("ALTER TABLE ..."); }// Prepared statement try (PreparedStatement stmt = connection.prepareStatement("SELECT * FROM ... ")) {// Remember not to pass the SQL string here!stmt.executeUpdate();// ... although, from an API perspective, this would be possible toostmt.executeUpdate("Some SQL here"); }OO
// Static statement DSL.using(connection, new Settings().withStatementType(StatementType.STATIC_STATEMENT)).fetch("SELECT * FROM AUTHOR")// Prepared statement DSL.using(connection).fetch("SELECT * FROM AUTHOR")5.帶有結(jié)果集的語句
另一方面,無法從JDBC語句類型推斷出該語句是否實際上是一個查詢返回結(jié)果集,或者它是否將返回許多更新的行,或者什么都不返回。 如果您不知道,則必須運行以下乏味的JDBC代碼:
JDBC
try (PreparedStatement stmt = connection.prepareStatement("SELECT FIRST_NAME FROM AUTHOR")) {// Use the little-known execute() methodboolean moreResults = stmt.execute();// Use the rarely-used do {} while (...) loopdo {// Check first, if there is any ResultSet availableif (moreResults) {try (ResultSet rs = stmt.getResultSet()) {while (rs.next()) {System.out.println(rs.getString(1));}}}else {System.out.println(stmt.getUpdateCount());}}// Repeat until there are neither any more result sets or update countswhile ((moreResults = stmt.getMoreResults()) || stmt.getUpdateCount() != -1); }OO
使用jOOQ,您可以按類型區(qū)分兩種類型的語句 :
- org.jooq.Query是具有更新計數(shù)且沒有結(jié)果的語句
- org.jooq.ResultQuery是帶有結(jié)果的語句
只有ResultQuery具有各種fetch()方法:
Query q1 = dsl.query("ALTER TABLE ..."); int rows = q1.execute();ResultQuery<?> q2 = dsl.resultQuery("SELECT * FROM AUTHOR"); Result<?> result = q2.fetch();翻譯自: https://www.javacodegeeks.com/2015/09/comparing-jooq-with-jdbc.html
總結(jié)
以上是生活随笔為你收集整理的将jOOQ与JDBC比较的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: tomcat不停机部署_Tomcat中的
- 下一篇: 迭代器生成器可迭代对象_使用迭代器时如何