我有以下 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/