mixjooq查询与jdbc事务

zzlelutf  于 2021-08-25  发布在  Java
关注(0)|答案(2)|浏览(696)

我有一个用例,我想将jdbc事务与jooq上下文混合使用。
jdbc代码如下所示:

  1. public void inTransaction(InTransaction lambda) {
  2. DataSource ds = dataSource.get();
  3. try (Connection connection = ds.getConnection()) {
  4. try {
  5. logger.info("set autocommit to false");
  6. connection.setAutoCommit(false);
  7. try (Statement statement = connection.createStatement()) {
  8. lambda.execute(statement);
  9. logger.info("commiting transaction");
  10. connection.commit();
  11. }
  12. } catch (RuntimeException e) {
  13. logger.info("rolling back transaction");
  14. connection.rollback();
  15. throw e;
  16. } finally {
  17. logger.info("set autocommit to true");
  18. connection.setAutoCommit(true);
  19. }
  20. } catch (SQLException e) {
  21. throw new TilerException(e);
  22. }
  23. }
  24. @FunctionalInterface
  25. public interface InTransaction {
  26. void execute(Statement statement) throws SQLException;
  27. }

我想要 lambda 参数,以便能够同时使用jdbc和jooq。
对于jdbc来说,使用语句非常简单。例如,像这样的图托拉尔:

  1. inTransaction(stmt -> {
  2. String SQL = "INSERT INTO Employees " +
  3. "VALUES (106, 20, 'Rita', 'Tez')";
  4. stmt.executeUpdate(SQL);
  5. String SQL = "INSERTED IN Employees " +
  6. "VALUES (107, 22, 'Sita', 'Singh')";
  7. stmt.executeUpdate(SQL);
  8. });

为了在同一事务上执行jooq查询,我必须获得一个上下文。我找到了一个api来从数据源/连接获取dslcontext。
我不清楚的是是否/如何创建jooq DSLContext 从一份声明中?

kpbwa7wx

kpbwa7wx1#

您描述的问题的解决方案

您可以使用jooq的事务api完成所有这一切:

  1. // Create this ad-hoc, or inject it, or whatever
  2. DSLContext ctx = DSL.using(dataSource, dialect);

然后:

  1. public void inJDBCTransaction(InJDBCTransaction lambda) {
  2. ctx.transaction(config -> {
  3. config.dsl().connection(connection -> {
  4. try (Statement statement = connection.createStatement()) {
  5. lambda.execute(statement);
  6. }
  7. });
  8. });
  9. }
  10. public void inJOOQTransaction(InJOOQTransaction lambda) {
  11. ctx.transaction(config -> lambda.execute(config.dsl()));
  12. }
  13. @FunctionalInterface
  14. public interface InJDBCTransaction {
  15. void execute(Statement statement) throws SQLException;
  16. }
  17. @FunctionalInterface
  18. public interface InJOOQTransaction {
  19. void execute(DSLContext ctx);
  20. }

您的最终代码:

  1. inJDBCTransaction(stmt -> {
  2. String SQL = "INSERT INTO Employees " +
  3. "VALUES (106, 20, 'Rita', 'Tez')";
  4. stmt.executeUpdate(SQL);
  5. String SQL = "INSERTED IN Employees " +
  6. "VALUES (107, 22, 'Sita', 'Singh')";
  7. stmt.executeUpdate(SQL);
  8. });
  9. inJOOQTransaction(ctx -> {
  10. ctx.insertInto(EMPLOYEES).values(106, 20, "Rita", "Tez").execute();
  11. ctx.insertInto(EMPLOYEES).values(107, 22, "Sita", "Singh").execute();
  12. });

我不太相信对jooq和jdbc进行这种抽象的必要性。jooq从不向您隐藏jdbc。当使用 DSLContext.connection() 方法。因此,如上所示:
jooq事务api正是您计划要做的事情。在事务上下文中 Package lambda,如果成功则提交,如果失败则回滚(您的版本的回滚无法工作,因为它捕获了错误的异常)。
如果需要“jdbc逃生舱”,jooq可以提供

旁注

在许多rdbms中,您不希望在静态jdbc上运行查询 Statement . 你会想用 PreparedStatement 而是因为:
您将从执行计划缓存中获益(并减少缓存上的争用)
您将避免语法错误(如果实际查询是动态的)
这样可以避免sql注入问题

展开查看全部
a6b3iqyw

a6b3iqyw2#

如果要从jooq获取查询字符串,可以调用

  1. String sqlString = query.getSQL()

然后在语句中使用此字符串:

  1. stmt.executeUpdate(sqlString);

相关问题