回答

收藏

带有jooq的kotlin手动编写表模型,无需代码生成

技术问答 技术问答 198 人阅读 | 0 人回复 | 2023-09-14

我正在使用jOOQ和Kotlin做实验,看到一些教程和文档,看起来很不错。
! X6 s7 o. b6 _9 n3 ?但是,如果使用jOOQ如果你觉得很烦人,你会生成代码。它似乎太复杂了,最终无法维护。我决定创建自己的手表模型(类似于休眠)。
& X/ e2 s- ?, D& c& o; _: ^我创建了两个表模型:
  e6 f" I, C# Z% M2 E用户
- A+ C8 x; B) `& s# Gdata class User(    val id: String = UUID.randomUUID().toString(),   val name: String,   val email: String,   val password: String? = null)    companion object        val TABLE: Table = DSL.table("user")        val ID: Field = DSL.field("id",String::class.java)        val USER_NAME: Field = DSL.field("user_name",String::class.java)        val EMAIL: Field = DSL.field("email",String::class.java)        val PASSWORD: Field = DSL.field("password",String::class.java)   追随者- T' r6 t0 h6 f. B* i6 R- x
data class Followers(    val id: String,   val followerId: String,   val userId: String)    companion object        val TABLE: Table = DSL.table("followers")        val ID: Field = DSL.field("id",String::class.java)        val FOLLOWER_ID: Field = DSL.field("follower_id",String::class.java)        val USER_ID: Field = DSL.field("user_id",String::class.java)   当我执行一些琐碎的事情时SQL它完美地工作了,但当我尝试下一个句子时,我遇到了异常。
3 _8 x0 ]/ K/ Q1 A2 freturn dsl.select().from(u.TABLE)            .rightJoin(f.TABLE).on(u.ID.eq(f.FOLLOWER_ID))            .where(u.ID.eq(id)).fetch().into(User::class.java)该代码的预期语句为:: Z- z4 s& L/ O
select *from user uright outer join followers fon u.id = f.follower_idwhere u.id = 'e30919bf-5f76-11e8-8c96-701ce7e27f83';但我从这个代码中得到的句子是:; e# C8 l: B2 q* l3 y- U0 g4 C
select *from user  right outer join followers  on id = follower_idwhere id = 'e30919bf-5f76-11e8-8c96-701ce7e27f83'当然,这会正确地告诉我 where子句中    的错误 列’id’
" `# f3 d- B+ F* J" I1 k3 D它提出了一些问题:
. s" T/ g$ b7 r- R4 k[ol]在没有代码生成的情况下,有没有更好的方法来声明表模型?; S0 x+ J% Q4 L. H
为什么DSLselect不能转化为正确的SQL句子?我做错了什么?[/ol]                                                               
# S1 m7 D( W* `1 R( {& c1 a  z    解决方案:                                                                ' c& t7 G' J9 w$ N. W
                                                                首先,一些不愿意使用代码生成的建议:我似乎太复杂了,最终无法维持。因此,我决定创建自己的手表模型(类似于休眠)。/ _9 S/ P% }- U) W
您(很可能)要经历很长的痛苦和磨难。首先,您现在已经需要考虑数据库迁移,最好使用数据库的DDL语言完成。这意味着从长远来看,数据库模型应该比客户模型更重要。事实上,您的客户端模型是数据库模型的副本,而不是您想要独立维护的东西。有了这个想法,代码生成器从数据库模型中生成客户端模型更为合理,反之亦然。' S' g3 T5 X( t9 d& E2 |5 T: }; U4 o* `
当然,项目启动时,Hibernate这也使得客户优先方法变得容易。但是,一旦投入生产,你 将9 e+ [( L6 _- y2 J) X6 f
必须迁移数据库,然后该模型将崩溃。您必须首先返回数据库,现在值得设置所有设置。
, r7 X. r1 [/ ?9 j所以不行。现在    代码生成可能会带来一些复杂性,但与创建自己的表模型相比, ,维护    代码将 更加容易    。
, ]' j" e; w1 Z8 {我在这里写了一篇关于主题的更长的博客文章。
! X) h0 I% ]5 B5 H, L1 P: j具体问题:return dsl.select().from(u.TABLE)          .rightJoin(f.TABLE).on(u.ID.eq(f.FOLLOWER_ID))          .where(u.ID.eq(id)).fetch().into(User::class.java)该代码的预期语句为:[…]
, M/ W+ w- Q0 u! c# q* X这取决于什么u和f是什么?你不能只是将军。Kotlin引用重命名表,期待引用重命名表jOOQ知道它们的意思。也就是说,您可以通过以下方式创建引用:
" n7 ]/ L% S% Y2 Y! O) ?) Jval u = User.TABLE;val f = Follower.TABLE;如果这是你引用的方式,那么根据身份,这两件事就是 同一件事    。jOOQ对你不会神奇Kotlin代码逆向工程,发现您想要表 别名
8 S: b/ S0 J! B1 `! u2 h0 z1 a。您必须告诉jOOQ:
& C* j8 D3 X$ }& X. ^val u = User.TABLE.as("u");val f = Follower.TABLE.as("f");但是你还没有完成。User.TABLE使用简单的SQL0 n% m1 c  G5 Z/ K( G
API构造引用意味着jOOQ操作时不了解表中的列。您不能再从别名表中引用这些列,因为它们是普通的SQL表的Table别名表的类型为,而不是User。
& A, x. z& \' E当然,你可以创建它TableImpl例子并在例子中注册所有列表TableImpl-就像代码生成器一样。在这种情况下,您将有与之相关的表 和$ `5 h1 P% j% Y- W* c7 E. _9 F
列,即使使用别名表可以安全使用。  \& }% @; e0 x4 B% t3 x
所有这些东西都是由生成的代码自动处理的,我再次建议你将其与之相匹配jOOQ一起使用。没有人使用代码生成器jOOQ一起使用的主要原因是数据模型是动态的,这在编译过程中是未知的。否则,您将为您完成大量自动重复代码生成器的工作。此外,如前所述,当您开始迁移架构时,您将在未来做更多的工作。
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则