Spring boot data R2DBC требует транзакции для операций чтения - PullRequest
1 голос
/ 14 октября 2019

Я пытаюсь получить список объектов из базы данных, используя Spring boot Webflux с драйвером postgres R2DBC, но я получаю сообщение об ошибке:

value ignored org.springframework.transaction.reactive.TransactionContextManager$NoTransactionInContextException: No transaction in context Context1{reactor.onNextError.localStrategy=reactor.core.publisher.OnNextFailureStrategy$ResumeStrategy@7c18c255}

кажется, что все операции DatabaseClient требуют переноса втранзакция.

Я пробовал разные комбинации зависимостей между spring-boot-data и r2db, но на самом деле не работал.

Версия:

        <spring-boot.version>2.2.0.RC1</spring-boot.version>
        <spring-data-r2dbc.version>1.0.0.BUILD-SNAPSHOT</spring-data-r2dbc.version>
        <r2dbc-releasetrain.version>Arabba-M8</r2dbc-releasetrain.version>

Зависимости:

<dependency>
  <groupId>org.springframework.data</groupId>
  <artifactId>spring-data-r2dbc</artifactId>
  <version>${spring-data-r2dbc.version}</version>
</dependency>
<dependency>
  <groupId>io.r2dbc</groupId>
  <artifactId>r2dbc-postgresql</artifactId>
</dependency>
<dependency>
  <groupId>org.postgresql</groupId>
  <artifactId>postgresql</artifactId>
</dependency>
<dependencyManagement>
<dependencies>
  <dependency>
    <groupId>io.r2dbc</groupId>
    <artifactId>r2dbc-bom</artifactId>
    <version>${r2dbc-releasetrain.version}</version>
    <type>pom</type>
    <scope>import</scope>
  </dependency>
</dependencies>
</dependencyManagement>
fun findAll(): Flux<Game> {
    val games = client
        .select()
        .from(Game::class.java)
        .fetch()
        .all()
        .onErrorContinue{ throwable, o -> System.out.println("value ignored $throwable $o") }
    games.subscribe()
    return Flux.empty()
}

@Table("game")
data class Game(@Id val id: UUID = UUID.randomUUID(),
                @Column("guess") val guess: Int = Random.nextInt(500))

Github repo: https://github.com/odfsoft/spring-boot-guess-game/tree/r2dbc-issue

Я ожидаю, что для операций чтения не требуется @Transactional или для выполнения запроса без переноса в транзакционный контекст вручную.

ОБНОВЛЕНИЕ: После нескольких попыток с несколькими версиями мне удается найти комбинацию, которая работает:

<spring-data-r2dbc.version>1.0.0.BUILD-SNAPSHOT</spring-data-r2dbc.version>
<r2dbc-postgres.version>0.8.0.RC2</r2dbc-postgres.version>

Зависимости:

<dependency>
  <groupId>org.springframework.data</groupId>
  <artifactId>spring-data-r2dbc</artifactId>
  <version>${spring-data-r2dbc.version}</version>
</dependency>
<dependency>
  <groupId>io.r2dbc</groupId>
  <artifactId>r2dbc-postgresql</artifactId>
  <version>${r2dbc-postgres.version}</version>
</dependency>
<dependencyManagement>
<dependencies>
  <dependency>
    <groupId>io.r2dbc</groupId>
    <artifactId>r2dbc-bom</artifactId>
    <version>Arabba-RC2</version>
    <type>pom</type>
    <scope>import</scope>
  </dependency>
</dependencies>
</dependencyManagement>

кажется версиинотация изменилась с 1.0.0.M7 до 0.8.x для r2dbc из-за следующего:

, нопосле обновления до последней версии появляется новая проблема, котораяявляется то, что транзакция требуется для выполнения запросов следующим образом:

Обновление конфигурации:

@Configuration
class PostgresConfig : AbstractR2dbcConfiguration() {

    @Bean
    override fun connectionFactory(): ConnectionFactory {
        return PostgresqlConnectionFactory(
            PostgresqlConnectionConfiguration.builder()
                .host("localhost")
                .port(5432)
                .username("root")
                .password("secret")
                .database("game")
                .build())
    }

    @Bean
    fun reactiveTransactionManager(connectionFactory: ConnectionFactory): ReactiveTransactionManager {
        return R2dbcTransactionManager(connectionFactory)
    }

    @Bean
    fun transactionalOperator(reactiveTransactionManager: ReactiveTransactionManager) =
        TransactionalOperator.create(reactiveTransactionManager)

}

Запрос:

    fun findAll(): Flux<Game> {
        return client
            .execute("select id, guess from game")
            .`as`(Game::class.java)
            .fetch()
            .all()
            .`as`(to::transactional)
            .onErrorContinue{ throwable, o -> System.out.println("value ignored $throwable $o") }
            .log()
    }

Отказ от ответственности, это не означает, что будет использоваться впроизводство !! еще до GA.

...