Jimmer Low Query KSP
自动收集自
lib/ksp/metadata/jimmer-low-query/README.md。
根据 Jimmer 实体字段上的注解生成强类型低代码查询函数,既能生成 KMutableRootQuery.ForEntity<E> 扩展,也能生成接收实体对象的 KSqlClient 查询入口。
推荐用法(插件优先)
plugins {
id("site.addzero.ksp.jimmer-low-query")
}
jimmerLowQuery {
// 可选:默认生成到 `<实体包>.generated.lowquery`
generatedPackage.set("com.example.generated.lowquery")
}
实体示例:
@JimmerLowQuery
@Entity
interface SystemConfig {
@Id
@OrderByDesc(priority = 0)
val id: Long
@Eq(name = "key")
val configKey: String
}
生成查询块扩展等价于:
public fun KMutableRootQuery.ForEntity<SystemConfig>.query(
key: String,
): KConfigurableRootQuery<KNonNullTable<SystemConfig>, SystemConfig> {
where(table.configKey `eq?` key)
orderBy(table.id.desc())
return select(table.fetchBy { allScalarFields() })
}
同时会生成一个 KSqlClient 扩展,调用方只需要传实体入参;实体类型由生成函数签名固定,字段、操作符、参数名、fetcher 等元信息全部来自实体注解:
val query = sqlClient.createLowQuery(
entity = entity,
)
生成结果等价于:
@JvmName("createLowQueryForSystemConfigByEntity")
public fun KSqlClient.createLowQuery(
entity: SystemConfig,
): KConfigurableRootQuery<KNonNullTable<SystemConfig>, SystemConfig> {
return createQuery(SystemConfig::class) {
if (ImmutableObjects.isLoaded(entity, "configKey")) {
where(table.configKey `eq?` entity.configKey)
}
orderBy(table.id.desc())
select(table.fetchBy { allScalarFields() })
}
}
实体入参建议用 Jimmer 草稿对象,只设置需要参与查询的字段;生成代码会用 ImmutableObjects.isLoaded(entity, "字段名") 判断字段是否已设置,未设置字段不会参与 where。
如果消费模块存在 Spring @Component,处理器还会为每个实体生成一个 JimmerLowQueryProvider<E> 组件,并用实体 KClass 作为运行时关联键。这样 crud-base 这类上游通用模块不需要静态 import 下游实体包里的 createLowQuery 扩展,也能在运行时从 Spring IoC 中找到对应实体的查询逻辑。
需要注意:createLowQuery 本身是实体包下的 Kotlin 扩展函数,普通跨模块调用要求“生成代码所在模块在 classpath 上,并在调用文件显式 import 对应 generated 包”。上游通用库无法反向看到下游实体模块,所以泛型 BaseController<E> 场景应走 Spring provider 注册表。
注解
@Eq(name = "", nullable = false):等值查询,生成动态谓词table.xxx `eq?` param。@Like(name = "", nullable = false):模糊查询,生成动态谓词table.xxx.`ilike?`(param, LikeMode.ANYWHERE)。@In(name = "", nullable = false):集合包含查询,生成动态谓词table.xxx `valueIn?` params;未指定name时默认用字段名简单复数形式。@OrderByAsc(priority = 0)/@OrderByDesc(priority = 0):排序注解,priority越小越先排序,生成orderBy(...)。@JimmerLowQuery(functionName = "query", clientFunctionName = "createLowQuery", visibility = PUBLIC, clientVisibility = PUBLIC, fetcher = ALL_SCALAR_FIELDS):可选,标在@Entity接口上,用于覆盖生成函数配置。@JimmerLowQueryParam(name = "", operator = EQ, nullable = false):兼容旧写法;新代码优先使用字段语义注解。
支持的字段语义注解:@Eq、@Ne、@Like、@StartsWith、@EndsWith、@Gt、@Ge、@Lt、@Le、@In、@NotIn。排序注解:@OrderByAsc、@OrderByDesc。
类上不写 @JimmerLowQuery 也可以,只要字段上有查询注解就会按默认配置生成:
@Entity
interface SystemConfig {
@Eq(name = "key")
val configKey: String
}
多字段示例:
@JimmerLowQuery(functionName = "queryByFilter")
@Entity
interface Device {
@Like(nullable = true)
val name: String
@In
val id: Long
}
上面 id 会生成参数 ids: Collection<Long>。
排序示例:
@Entity
interface PowerRuntimeStatus {
@OrderByDesc(priority = 0)
val snapshotTime: LocalDateTime
@OrderByDesc(priority = 1)
val id: Long
}
生成排序等价于:
orderBy(table.snapshotTime.desc(), table.id.desc())
groupBy 暂不做注解化封装,因为它通常会改变 select 结果形状和返回类型;聚合查询继续直接使用 Jimmer 原生 DSL。
Raw KSP fallback
不推荐优先使用 raw KSP;只有插件不可用时才手动接线:
dependencies {
implementation("site.addzero:jimmer-low-query-annotations:<version>")
ksp("site.addzero:jimmer-low-query-processor:<version>")
}
ksp {
arg("jimmerLowQuery.generatedPackage", "com.example.generated.lowquery")
}
processorBuddy.mustMap 参数:
jimmerLowQuery.generatedPackage:生成包名;留空时使用<实体包>.generated.lowquery。