从jooq查询创建一个PreparedStatement

3

我目前正在探索 JOOQ 的可能性,想要谨慎起见,仅将 JOOQ 用作 SQL 构建器。我将数据库模式定义为从 CustomTable 派生的类,以获得类型安全性。

这会导致以下代码:

Param<Integer> pId = ...
Query query = context.select(sometable.somefield.max())
                     .from(sometable)
                     .where(sometable.id.eq(pId)
                     ;

这里的sometable是一个变量,它持有我的一个表实例。

目前我对query所做的操作类似于:

PreparedStatement pstmt = connection.prepareStatement(query.getSQL());
pstmt.setObject(1, pId.getValue(), pId.getDataType().getSQLType());

但是,一旦语句有更多参数,我开始在JOQQ的实现中遇到复杂的依赖关系,特别是对于setObject的第一个参数。我想使用query.getBindValues(),但这只返回要绑定到语句的普通Java对象。我必须假设顺序与setObject的位置顺序匹配,并且此外我现在缺少getSQLType()。因此,这也不是一个好方法。然后,我希望能找到类似于query.getPreparedStatement(connection)这样的东西,以从提供的连接中创建陈述并填充所有参数,但似乎不存在这种方法。我是否错过了一些巧妙的方法可以从JOOQ Query中获取PreparedStatement呢?

为了完整起见,您能否简要解释一下为什么不想使用jOOQ来执行查询? - Lukas Eder
我还没有完全准备好彻底地献身于 JOOQ :-) 除此之外,我读到 JOOQ 最初是作为一个 SQL 构建器开始的,我认为有自然的三个责任分离:1)正确获取查询或语句,2)使用池、连接、语句等处理与数据库的连接,3)从查询结果中读取数据。通过交换 PreparedStatement 和 Connection 以及 JOOQ 查询,可以很好地实现(1)和(2)之间的分离。 - Harald
你的灵魂可以奔跑,但它无处可藏。jOOQ已经准备了5年的语句 - 被大型企业用于生产...不确定你在担心什么 :) 从一开始,jOOQ就将变量绑定到PreparedStatement中。SQL提取功能稍后才出现。无论如何,我会给出一个答案。 - Lukas Eder
1个回答

3
默认情况下,每次运行Query.execute()或任何ResultQuery.fetch()方法时,jOOQ内部都会创建PreparedStatements。我认为允许用户准备语句,并通过一个新的方法Query.statement()访问这些未执行的语句可能是一个好主意。我已将此添加为一个功能请求: 今天,您可以使用您提到的 API 自己提取 SQL 和绑定变量,基本上是您描述的方式(请注意,还有 Query.getParams()),它按绑定顺序返回Param类型。
但是请注意,通常没有真正好的理由(除了在非常高的吞吐量场景中进行SQL字符串缓存)通过JDBC直接提取SQL字符串并执行它。jOOQ主要用于渲染SQL并执行它。

感谢您将此视为功能请求。如果我有发言权,我会强烈推荐使用ResultQuery.statement(Connection con),因为只有这样才允许我保持对连接的所有权,仅借用它来创建语句给 JOOQ。 - Harald
@Harald:虽然你可能更喜欢在特定情况下使用该API,但在jOOQ API的整体上下文中,这将是非常令人惊讶的。在任何可比较的方法中,几乎没有任何关于Connection的参考,因此在那里添加它是没有意义的。本质上,将会有ResultQuery.statement()和可能的DSLContext.statement(ResultQuery)。两种方法都将与现有的ResultQuery.keepStatement()行为保持一致。我希望这样说得通? - Lukas Eder
我不确定是否应该添加方法调用,因为我对这个语句该怎么处理并不确定。它来自于一个连接,而我在调用的地方并没有真正拥有它,所以我想知道是否有必要对这个语句做任何事情。但是我承认,我还没有深入了解JDBC。 - Harald
确实是一个边缘情况,但在jOOQ中已经有可能访问JDBC ResultSet,因此访问PreparedStatement并不令人惊讶。一个用例是手动批处理,或者连续执行具有新绑定值的缓存语句...好吧,这些都是边缘情况 :-) - Lukas Eder

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接