将jOOQ与JDBC比较

本文是我们学院课程的一部分,标题为jOOQ –类型安全的数据库查询

在SQL和特定关系数据库很重要的Java应用程序中,jOOQ是一个不错的选择。 当JPA / Hibernate抽象过多,JDBC过多时,这是一种替代方法。 它显示了一种现代的领域特定语言如何可以极大地提高开发人员的生产率,从而将SQL内部化为Java。

在本课程中,我们将看到如何使用jOOQ有效地查询数据库。 在这里查看

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 SQLException
    while (rs.next()) {

        // This can throw a SQLException
        System.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 too
    stmt.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() method
    boolean moreResults = stmt.execute();

    // Use the rarely-used do {} while (...) loop
    do {

        // Check first, if there is any ResultSet available
        if (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 counts
    while ((moreResults = stmt.getMoreResults()) || stmt.getUpdateCount() != -1);
}

OO

使用jOOQ,您可以按类型区分两种类型的语句

只有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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值