spring - 带有 TransactionAwareDataSourceProxy 的 jooq DataSourceConnectionProvider 不参与 Spring 事务

标签 spring hibernate jooq spring-transactions hikaricp

我有以下 Spring 数据源设置:

 datasource:
    name: postgres-datasource
    url: ${POSTGRES_URL:jdbc:postgresql://localhost:5432/mydb}?reWriteBatchedInserts=true&prepareThreshold=0
    username: ${POSTGRES_USER:mydb}
    password: ${POSTGRES_PASS:12345}
    driver-class: org.postgresql.Driver
    hikari:
      minimumIdle: 2
      maximum-pool-size: 30
      max-lifetime: 500000
      idleTimeout: 120000
      auto-commit: false
      data-source-properties:
        cachePrepStmts: true
        useServerPrepStmts: true
        prepStmtCacheSize: 500
  jpa:
    database-platform: org.hibernate.dialect.PostgreSQLDialect
    properties:
      hibernate:
        dialect: org.hibernate.dialect.PostgreSQLDialect
#        generate_statistics: true
        order_inserts: true
        order_updates: true
        jdbc:
          lob:
            non_contextual_creation: true
          batch_size: 50

请注意,自动提交为false
由于我需要同时使用 jooq 和 JPA,并且数据库中有多个架构,因此我配置了以下 DataSourceConnectionProvider

public class SchemaSettingDataSourceConnectionProvider extends DataSourceConnectionProvider {

    public SchemaSettingDataSourceConnectionProvider(TransactionAwareDataSourceProxy dataSource) {
        super(dataSource);
    }

    public Connection acquire() {
        try {
            String tenant = TenantContext.getTenantId();
            log.debug("Setting schema to {}", tenant);
            Connection connection = dataSource().getConnection();
            Statement statement = connection.createStatement();
            statement.executeUpdate("SET SCHEMA '" + tenant + "'");
            statement.close();
            return connection;
        } catch (SQLException var2) {
            throw new DataAccessException("Error getting connection from data source " + dataSource(), var2);
        }
    }

我在 Spring Boot 配置上有 @EnableTransactionManagement 。完成此设置后,事务结束后不会提交连接。

@Transactional(propagation = Propagation.REQUIRES_NEW)
    public FlowRecord insert(FlowName name, String createdBy) {
        return dslContext.insertInto(FLOW, FLOW.NAME, FLOW.STATUS)
                .values(name.name(), FlowStatus.CREATED.name())
                .returning(FLOW.ID)
                .fetch()
                .get(0);
    }

这不会提交。因此,我尝试将以下代码添加到我的 SchemaSettingDataSourceConnectionProvider

@Override
    public void release(Connection connection) {
        connection.commit();
        super.release(connection);
    }

但是,现在的问题是,即使事务应该回滚(例如由于运行时异常),它仍然会始终提交。

是否缺少一些配置

更新 根据下面的答案,我提供了一个 DataSourceTransactionManager bean,它适用于 JOOQ。

public DataSourceTransactionManager jooqTransactionManager(DataSource dataSource) {
        // DSTM is a PlatformTransactionManager
        return new DataSourceTransactionManager(dataSource);
    }

但是,现在我的常规 JPA 调用都失败了

Caused by: javax.persistence.TransactionRequiredException: Executing an update/delete query
    at org.hibernate.internal.AbstractSharedSessionContract.checkTransactionNeededForUpdateOperation(AbstractSharedSessionContract.java:445)
    at org.hibernate.query.internal.AbstractProducedQuery.executeUpdate(AbstractProducedQuery.java:1692)

因此,我提供了一个 JpaTransactionManager bean。现在这会导致 JOOQ 自动配置抛出多个 DataSourceTransactionManager beans 存在异常。经过多次尝试和错误,对我有用的是:

private final TransactionAwareDataSourceProxy dataSource;

    public DslConfig(DataSource dataSource) {
        // A transaction aware datasource is needed, otherwise the spring @Transactional is ignored and updates do not work.
        this.dataSource = new TransactionAwareDataSourceProxy(dataSource);
    }

    @Bean("transactionManager")
    public PlatformTransactionManager transactionManager() {
        // Needed for jpa transactions to work
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setDataSource(dataSource);
        return transactionManager;
    }

请注意,我使用的是 JpaTransactionManager,但将 datasource 设置为 TransactionAwareDataSourceProxy。需要进一步测试,但看起来 JPA 和 JOOQ 事务现在都可以正常工作。

最佳答案

需要注意的一件事是确保您使用正确的 @Transactional 注释。在我的项目中,有两个:一个来自 Jakarta 包,另一个来自 Spring 包 - 确保您使用的是 Spring 注释。

我不知道你的Spring配置是否正确。 我们使用 Java 配置,因此很难比较。

一个明显的区别是我们有一个明确的 TransactionManager已定义,这是您可能需要做的事情吗?

关于spring - 带有 TransactionAwareDataSourceProxy 的 jooq DataSourceConnectionProvider 不参与 Spring 事务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74511655/

相关文章:

mysql - admin 不以一对一关系保存在用户表中 spring boot

java - Spring AOP,切入点根据路径变量名触发

java - 在tomcat中部署Spring boot应用程序

带有 SQL Server 2012 的 Java Hibernate 不工作?

java - Spring Boot 中带有 Stomp 的 JAX RS 和 WebSockets 发生冲突

java - 将 jpa (Hibernate) 中的 native (连接)查询转换为 json

java - 关闭打开的 hibernate session (如果存在)

maven-3 - org.jooq.codegen.GeneratorException : Error while reading XML configuration

gradle - 无法使用 gradle-jooq-plugin-3.0.1、jooq-3.11.2 找到或加载主类 org.jooq.codegen.GenerationTool

java - Jooq 中替代的 SQL DATE_FORMAT