本人使用的IDEA版本是比较新的版本(2024.3.1),在体验Jimmer的时候遇到了一些问题并尝试解决,在此分享一些使用经验

本人使用的Kotlin+Gradle的项目构建方式

项目构建报错:Unable to load class 'org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinCompilationData'.

造成这个问题的原因是部分plugins的版本并不匹配。

报错时我的gradle相关配置如下:

plugins {
    kotlin("jvm") version "1.9.25"
    kotlin("plugin.spring") version "1.9.25"
    id("org.springframework.boot") version "3.4.3"
    id("io.spring.dependency-management") version "1.1.7"
    id("com.google.devtools.ksp") version "1.7.10-1.0.6"
}

这里的ksp插件版本和jvm和plugin.spring的插件不匹配,修改为如下内容后可以实现正常构建

plugins {
    kotlin("jvm") version "1.9.22"
    kotlin("plugin.spring") version "1.9.22"
    id("org.springframework.boot") version "3.2.3"
    id("io.spring.dependency-management") version "1.1.4"
    id("com.google.devtools.ksp") version "1.9.22-1.0.17"
}

项目运行报错:‘No qualifying bean of type 'org.babyfish.jimmer.sql.kt.KSqlClient' available’

这是因为没有在配置文件中配置Jimmer的语言是kt还是java,在application.yaml 中添加一下配置即可:

jimmer:
    language: kotlin
    dialect: org.babyfish.jimmer.sql.dialect.MySqlDialect

查看OpenApi的时候报错:No type definition for "java.lang.Class"

笔者在遇到这个问题的时候,是因为controller的代码如下所示,除此之外还需要将后端的应用启动类加上注解@EnableImplicitApi

    @GetMapping("/{id}")
    fun get(@PathVariable id: Long): Mono<ApiResponse<EnergyType>>   {
        return ApiResponse.success(energyTypeRepository.findById(id).orElse(null))
    }

    @DeleteMapping("/{id}")
    fun delete(@PathVariable id: Long): Mono<ApiResponse<Void>> {
        energyTypeRepository.deleteById(id)
        return ApiResponse.success()
    }

Jimmer没有读取到对应的dto对象的数据结构,且有些返回的Void不应当被读取,因此需要将controller的代码修改一下,添加FetchBy 注解指定自动生成的Dto

    @GetMapping("/{id}")
    fun get(@PathVariable id: Long): Mono<ApiResponse<@FetchBy("ENERGY_TYPE") EnergyType>>   {
        return ApiResponse.success(energyTypeRepository.findById(id).orElse(null))
    }

    @DeleteMapping("/{id}")
    @ApiIgnore
    fun delete(@PathVariable id: Long): Mono<ApiResponse<String>> {
        energyTypeRepository.deleteById(id)
        return ApiResponse.success(null)
    }
    companion object {
        private val ENERGY_TYPE =
            newFetcher(EnergyType::class).by{
                allScalarFields()
            }
    }

这里贴出 ApiResponse的代码:


data class ApiResponse<T>(
    val success: Boolean,
    val code: Int,
    val message: String,
    val data: T?
) {

    companion object {
        fun <T> success(): ApiResponse<T> {
            return ApiResponse(true, 200, "Success", null)
        }

        fun <T> success(data: T): ApiResponse<T> {
            return ApiResponse(true, 200, "Success", data)
        }

        fun <T> error(message: String): ApiResponse<T> {
            return ApiResponse(false, 500, message, null)
        }

        fun <T> error(code: Int, message: String): ApiResponse<T> {
            return ApiResponse(false, code, message, null)
        }
    }

}