[英]How to select the correct TransactionManager when using R2DBC together with Flyway and JDBC
Setup:设置:
Test Configuration (conf4k):测试配置(conf4k):
datasources {
default {
dialect=POSTGRES
options {
currentSchema=default
}
}
}
r2dbc {
datasources {
default {
dialect=POSTGRES
options {
currentSchema=default
}
}
}
}
flyway {
datasources {
default {
enabled=true
locations="classpath:databasemigrations"
schemas=["default"]
create-schemas=true
}
}
}
test-resources {
containers {
postgres {
image-name="postgres:12.12"
hostnames=["localhost"]
}
}
}
Preconditions:先决条件:
To make Flyway and micronaut data use the same database and testcontainer, the datasource of both needs to be named alike.为了使 Flyway 和 micronaut 数据使用相同的数据库和测试容器,两者的数据源需要命名相同。
Problem:问题:
Because of JDBC and R2DBC beeing used at the same time, synchronous and reactive TransactionManagers beans are created and I get the following error, when I use @Transactional:由于同时使用 JDBC 和 R2DBC beeing,因此创建了同步和反应式 TransactionManagers bean,当我使用 @Transactional 时出现以下错误:
Multiple possible bean candidates found: [io.micronaut.transaction.jdbc.DataSourceTransactionManager, io.micronaut.transaction.sync.SynchronousFromReactiveTransactionManager]
Thoughts:想法:
I thought, I could solve that with @TransactionalAdvice, but since both datasources need to have the same name, this is not possible.我想,我可以用@TransactionalAdvice 解决这个问题,但由于两个数据源需要具有相同的名称,所以这是不可能的。 I tried to name the datasources differently, but does not work at all.我试图以不同的方式命名数据源,但根本不起作用。
You can try to change the datasource name of Jdbc(default) and Flyway(Flyway depends on Jdbc Datasouce) to another name, then in your Jdbc Repository, use a @TransactionalAdvice
to select it.你可以试试把Jdbc(default)和Flyway(Flyway depends on Jdbc Datasouce)的datasource name改成别的名字,然后在你的Jdbc Repository中,使用一个@TransactionalAdvice
给select吧。
I have a Micronaut example using Flyway and R2dbc in the same project.我有一个在同一个项目中使用 Flyway 和 R2dbc 的 Micronaut 示例。
But I have not tried @Transactional
, for the transaction handling, I was using R2dbcOperations.withTransaction
, it works well.但是我没有尝试过@Transactional
,对于事务处理,我使用的是R2dbcOperations.withTransaction
,效果很好。
public Mono<Long> deleteAll() {
var sql = "DELETE FROM customers";
return Mono.from(
r2dbcOperations.withTransaction(status ->
Mono.just(status.getConnection())
.flatMap(connection -> Mono
.from(connection.createStatement(sql).execute())
.flatMap(result -> Mono.from(result.getRowsUpdated()))
)
)
);
}
Check my Micronaut R2dbc example here , hope it is helpful. 在此处查看我的 Micronaut R2dbc 示例,希望对您有所帮助。
As Hantsy mentioned in his post, adding transactions programmatically using R2dbcOperations#withTransaction()
is a temporary workaround until Flyway finally supports R2DBC.正如Hantsy在他的帖子中提到的,在 Flyway 最终支持 R2DBC 之前,使用R2dbcOperations#withTransaction()
以编程方式添加事务是一种临时解决方法。 Please upvote here .请在这里投票。
Since I use Kotlin and Coroutines, the code is suboptimal but ok for a hopefully ephemeral solution.由于我使用 Kotlin 和 Coroutines,代码不是最理想的,但对于希望短暂的解决方案来说还可以。 To use that in Kotlin, one has to wrap the body of the function passed to withTransaction
in mono {}
.要在 Kotlin 中使用它,必须将传递给withTransaction
的 function 的主体包装在 mono {}
中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.