Java 使用Jooq创建通用存储库
我们正在使用JOOQ映射现有数据库。此数据库中的每个表(栏1)共享一组类似的列:Java 使用Jooq创建通用存储库,java,spring-boot,kotlin,generics,jooq,Java,Spring Boot,Kotlin,Generics,Jooq,我们正在使用JOOQ映射现有数据库。此数据库中的每个表(栏1)共享一组类似的列: resource_id: Int (FK) id: Int (PK) identifier: UUID date_created: DateTime date_modified: DateTime 数据库中有一条适用于所有操作的一般规则,如下所示: select * from table t join resource r on r.id = t.resou
resource_id: Int (FK)
id: Int (PK)
identifier: UUID
date_created: DateTime
date_modified: DateTime
数据库中有一条适用于所有操作的一般规则,如下所示:
select *
from table t
join resource r on r.id = t.resource_id
where r.is_archived = false
使用JOOQs生成功能,我可以成功创建一个存储库类,该类实现基本查询操作:
@Repository
class UserRepository(val dsl:DSLContext): IRepository {
val record = Tables.AUTHENTICATION_USER!! //generated by jooq
val resource = Tables.RESOURCE!! //generated by jooq
val pojo = AuthenticationUser::class.java //generated by jooq
// this is the general query logic that should be applied to all the things
override fun selectQuery(): SelectConditionStep<Record> {
return dsl
.select(record.asterisk())
.from(record)
.join(resource).on(resource.ID.eq(record.RESOURCE_ID))
.where(resource.IS_ARCHIVED.eq(false))
}
override fun asyncCount(): Mono<Int> = Mono.fromCallable {
selectQuery()
.count()
}
fun asyncGetPage(from: Int,
size: Int,
orderBy: SortField<*> = record.DATE_CREATED.asc(),
) = Mono.fromCallable {
selectQuery()
.orderBy(orderBy)
.limit(size)
.offset(from)
.fetchInto(pojo)
.let { Collections.unmodifiableList(it) }
}
当我尝试使用表T
执行任何操作时,问题就出现了。由于T
是一种通用表类型,编译器无法知道字段id
、identifier
、resource\u id
、date\u created
等,这意味着这样的查询无法编译:
fun asyncGetAllNonArchived() =
dsl
.select()
.from(table)
.where(table.DATE_CREATED > ...)
问题:
有没有一种方法可以告诉编译器或以公共字段可用的方式声明泛型
编辑:感谢下面卢卡斯·埃德的建议。通过调整该解决方案,我们能够创建一个通用存储库 首先,将生成器策略更改为Kotlin,让
可审核的接口正确动作:)
其次,我们找不到泛型类实现表
类型的记录
类型的方法,因此您必须稍微扩展签名
interface Auditable {
fun RESOURCE_ID(): TableField<Record, Int> =
(this as Table<Record>).field("resource_id") as TableField<Record, Int>
fun ID(): TableField<Record, Int> =
(this as Table<Record>).field("id") as TableField<Record, Int>
fun IDENTIFIER(): TableField<Record, UUID> =
(this as Table<Record>).field("identifier") as TableField<Record, UUID>
fun DATE_CREATED(): TableField<Record, LocalDateTime> =
(this as Table<Record>).field("date_created") as TableField<Record, LocalDateTime>
fun DATE_MODIFIED(): TableField<Record, LocalDateTime> =
(this as Table<Record>).field("date_modified") as TableField<Record, LocalDateTime>
}
open class GeneralRepository<R, T>(val table: T) where R: Record, T: Table<R>, T: Auditable {
val resource = Resource.RESOURCE
fun selectQuery() =
dsl
.select(table.asterisk())
.from(table)
.join(resource).on(resource.ID.eq(table.RESOURCE_ID()))
.where(resource.IS_ARCHIVED.eq(false))
接口可审核{
乐趣资源_ID():TableField=
字段(“资源_id”)作为表字段
fun ID():TableField=
字段(“id”)作为TableField
趣味标识符():TableField=
字段(“标识符”)作为TableField
趣味日期_CREATED():TableField=
字段(“创建日期”)作为表格字段
趣味日期_MODIFIED():TableField=
(此为表格)。字段(“修改日期”)为表格字段
}
打开类GeneralRepository(val table:T),其中R:Record,T:table,T:Auditable{
val resource=resource.resource
fun selectQuery()=
数字用户线
.选择(表.asterisk())
.来自(表)
.join(resource).on(resource.ID.eq(table.resource\u ID()))
.where(resource.IS_.eq(false))
然后,您可以轻松实现通用扩展:
class UserRepo: GeneralRepository<UserRecord, User>(table = User.USER) {
fun getEmail(email: String) = Mono.fromCallable {
selectQuery().and(table.EMAIL.eq(email))
}
}
class UserRepo:GeneralRepository(table=User.User){
fun getEmail(email:String)=Mono.fromCallable{
选择query()和(table.EMAIL.eq(EMAIL))
}
}
您可以生成一个界面,提供对以下列的访问:
接口可审核{
乐趣资源\u ID():表字段=
字段(“资源_id”)作为表字段
乐趣ID():表字段=
字段(“id”)作为TableField
趣味标识符():TableField=
字段(“标识符”)作为TableField
乐趣日期\u已创建():TableField=
字段(“创建日期”)作为表格字段
乐趣日期\u修改():表字段=
(此为表格)。字段(“修改日期”)为表格字段
}
然后使用以下命令将接口附加到所有生成的表:
T_*
com.example.Auditable
当前无法在接口中声明属性,因为无法检测是否需要重写
修饰符,请参阅
但现在这可能已经足够好了。然后您可以创建如下通用条件:
select *
from table t
join resource r on r.id = t.resource_id
where r.is_archived = false
funDateCreatedCondition(表:T,dt:LocalDateTime):条件
其中T:Table,T:Auditable=Table.DATE_CREATED().gt(dt)
您是否知道,您可以在Stack Overflow上为自己的问题提供答案,而不是编辑您的问题。这样,对该问题的未来访问者可能更有帮助