Spring Data r2dbc 转换器<Row, Entity> 不工作

问题描述 投票:0回答:1

我尝试在@Query中实现一对一关系查询。相关表结构如下

@Table("t_author")
data class Author(
    @field:Id
    val id: Long,
    var name: String,
)

@Table("t_book")
data class Book(
    @field:Id
    val id: Long,
    var title: String,
    var authorId: Long,
    var publishTime: Instant,
    var author: Author? // Associated 't_author'
)

我的查询定义如下

@Repository
interface BookRepository : R2dbcRepository<Book, Long> {

    @Query(
        """
        SELECT b.*, a.name AS author_name 
        FROM t_book b
        LEFT JOIN t_author a ON b.author_id = a.id
        WHERE b.id = :id
    """
    )
    fun bookAndAuthorById(@Param("id") id: Long): Mono<Book>
}

我尝试将上面sql的返回结果映射到Book.class,我尝试定义一个转换器。

import io.r2dbc.spi.Row
import org.springframework.core.convert.converter.Converter
import org.springframework.data.convert.ReadingConverter
import java.time.Instant


@ReadingConverter
class BookConverter : Converter<Row, Book> {
    override fun convert(source: Row): Book {

        println("BookConverter.convert()")

        return Book(
            id = source.get("id", Long::class.java)!!,
            title = source.get("title", String::class.java)!!,
            publishTime = source.get("publish", Instant::class.java)!!,
            authorId = source.get("author_id", Long::class.java)!!,
            author = Author(
                id = source.get("author_id", Long::class.java)!!,
                name = source.get("author_name", String::class.java)!!
            )
        )
    }
}

并在配置类中使用,

@EnableR2dbcRepositories
@Configuration
class R2DbcConfig {

    @Bean
    @ConditionalOnMissingBean
    fun r2dbcCustomConversions(): R2dbcCustomConversions {

        println("R2DbcConfig.r2dbcCustomConversions()")

        return R2dbcCustomConversions.of(
            MySqlDialect.INSTANCE,
            BookConverter() // use
        )
    }
}

最后我的测试结果如下,

@field:Autowired
lateinit var bookRepository: BookRepository

@field:Autowired
lateinit var r2dbcCustomConversions: R2dbcCustomConversions

@Test
fun testRepositoryJoin() {
    val source = bookRepository.bookAndAuthorById(1L)
        .log()

    // println(r2dbcCustomConversions)

    StepVerifier.create(source)
        .expectNextMatches { // assert author is not null
            it.author != null
        }
        .verifyComplete()
}

输出如下,

...
R2DbcConfig.r2dbcCustomConversions()
2024-01-06T09:57:26.609+08:00  INFO 3416 --- [    Test worker] com.origami.r2dbc.SpringDataR2dbcTest    : Started SpringDataR2dbcTest in 3.28 seconds (process running for 5.131)
...
2024-01-06T09:57:27.780+08:00  INFO 3416 --- [    Test worker] reactor.Mono.Next.1                      : onSubscribe(MonoNext.NextSubscriber)
2024-01-06T09:57:27.783+08:00  INFO 3416 --- [    Test worker] reactor.Mono.Next.1                      : request(unbounded)
2024-01-06T09:57:29.124+08:00  INFO 3416 --- [actor-tcp-nio-2] reactor.Mono.Next.1                      : onNext(Book(id=1, title=Origami, authorId=1, publishTime=2024-01-05T14:13:22Z, author=null))
2024-01-06T09:57:29.129+08:00  INFO 3416 --- [actor-tcp-nio-2] reactor.Mono.Next.1                      : cancel()
2024-01-06T09:57:29.130+08:00  INFO 3416 --- [actor-tcp-nio-2] reactor.Mono.Next.1                      : onComplete()

我们可以看到输出只包含“R2DbcConfig.r2dbcCustomConversions()”,而不包含“BookConverter.convert()”。

而且我用IDE的debug查看“r2dbcCustomConversions”的结果,发现里面有“BookConveter”,但是并没有生效。 (此 -> r2dbcCustomConversions -> 转换器)

  • The result of debug 1
  • The result of debug 2

我在上一篇中看到了它,但它不起作用,如何解决这个问题。

build.gradle.kts

plugins {
    id("org.springframework.boot") version "3.2.1"
    id("io.spring.dependency-management") version "1.1.4"
    kotlin("jvm") version "1.9.21"
    kotlin("plugin.spring") version "1.9.21"
}

dependencies {
    implementation("org.springframework.boot:spring-boot-starter-data-r2dbc")
    implementation("org.springframework.boot:spring-boot-starter-webflux")
    implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
    implementation("io.projectreactor.kotlin:reactor-kotlin-extensions")
    implementation("org.jetbrains.kotlin:kotlin-reflect")
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor")
    runtimeOnly("com.mysql:mysql-connector-j")
    runtimeOnly("io.asyncer:r2dbc-mysql")
    testImplementation("io.asyncer:r2dbc-mysql")
    testImplementation("org.springframework.boot:spring-boot-starter-test")
    testImplementation("io.projectreactor:reactor-test")
}

我想知道为什么转换器不起作用。我也尝试过将 Kotlin 更改为 Java 代码,但也不起作用。

java spring-boot kotlin spring-webflux spring-data-r2dbc
1个回答
0
投票

我可能已经找到了解决方案,我尝试将 Spring Boot 版本更改为“3.1.6”并且它有效

plugins {
    id("org.springframework.boot") version "3.1.6"
    // ...
}

© www.soinside.com 2019 - 2024. All rights reserved.