本文是我们学院课程的一部分,标题为jOOQ –类型安全的数据库查询 。
在SQL和特定关系数据库很重要的Java应用程序中,jOOQ是一个不错的选择。 当JPA / Hibernate抽象过多,JDBC过多时,这是一种替代方法。 它显示了一种现代的领域特定语言如何可以极大地提高开发人员的生产率,从而将SQL内部化为Java。
在本课程中,我们将看到如何使用jOOQ有效地查询数据库。 在这里查看 !
目录
- 1.简介 2.检查异常
- 2.1。 JDBC 2.2。 OO
3.结果集 - 3.1。 您可以在foreach循环中使用jOOQ结果 3.2。 您可以将jOOQ结果与Java 8流一起使用
4.准备的陈述 - 4.1。 JDBC 4.2。 OO
5.带有结果集的语句 - 5.1。 JDBC 5.2。 OO
1.简介
也可以从org.jooq.academy.section3包中获得本节中显示的示例 。
大多数Java开发人员对JDBC是什么以及它如何工作都有深刻的了解。 如果还没有的话,请查看Oracle的官方JDBC教程以了解有关JDBC的更多信息。
JDBC通常因冗长而受到批评。 JDBC也因选择了错误的“默认值”而受到批评,例如,默认的结果集的延迟实现。 我们将看到jOOQ如何改进这些批评:
2.检查异常
Java的检查异常已被视为失败,这也是Java 8的新Streams API和所有相关功能接口不再支持检查异常的原因。
jOOQ的所有API都将抛出从jOOQ的org.jooq.exception.DataAccessException
派生的RuntimeExceptions
,在大多数情况下您无需捕获它,从而使其中止当前的正在运行的事务。 比较两者的示例:
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.结果集
JDBC的ResultSet
是一个非常有状态的对象,无法与Java collections API很好地互操作。 例如,它没有实现Iterator
,因为它还必须适应在基础数据库游标中向后滚动-几乎任何人都不需要的功能。
jOOQ通过org.jooq.Result
类型更好地集成了SQL结果集,可容纳所有用例的95%:
- jOOQ的
Result
实现了java.util.List
,因此继承了List
的所有功能,包括将其转换为Java 8 Stream的功能 。 - jOOQ的
Result
已完全实现到Java内存中,而不是默认情况下是惰性的。 这样可以尽早释放资源。 - jOOQ的
Result
知道其自己的Record
类型,该类型允许通过列引用而不是列索引进行类型安全的访问记录属性。
请注意,以上是默认设置。 如果您有较大的结果集,并且不想逐条记录地实现,则可以始终使用jOOQ的惰性获取功能。 在以下示例中可以看出:
您可以在foreach循环中使用jOOQ结果
for (Record record : DSL.using(connection).select().from(AUTHOR).fetch()) {System.out.println(record);
}
您可以将jOOQ结果与Java 8流一起使用
DSL.using(connection).select().from(AUTHOR).fetch().stream().flatMap(record -> Arrays.stream(record.intoArray())).forEach(System.out::println);
4.准备的陈述
奇怪的是,JDBC区分静态java.sql.Statement
类型和java.sql.PreparedStatement
类型。 这种做法将使您不必执行往返数据库的操作即可在执行之前准备语句-但是,无论如何,最好使用准备好的语句来执行所有查询的95%,所以为什么要打扰呢?
jOOQ不会通过单独的语句类型来区分这两种执行模式 。 相反,您可以使用设置标志来指示在真正需要时应执行静态语句。 一个例子:
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.带有结果集的语句
另一方面,无法从JDBC语句类型推断出该语句是否实际上是一个查询返回结果集,或者它是否将返回许多更新的行,或者什么都不返回。 如果您不知道,则必须运行以下乏味的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,您可以按类型区分两种类型的语句 :
-
org.jooq.Query
是具有更新计数且没有结果的语句 -
org.jooq.ResultQuery
是带有结果的语句
只有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