我正在尝试使用jOOQ和Kotlin并看到一些教程和文档,它看起来非常好.
但是如果jOOQ有一些非常烦人的东西就是代码生成.这似乎太复杂了,最终无法维持.我决定创建自己的表模型(类似于hibernate的工作原理).
我创建了两个表模型:
用户
data class User(
val id: String = UUID.randomUUID().toString(),
val name: String,
val email: String,
val password: String? = null
) {
companion object {
val TABLE: Table<Record> = DSL.table("user")
val ID: Field<String> = DSL.field("id", String::class.java)
val USER_NAME: Field<String> = DSL.field("user_name", String::class.java)
val EMAIL: Field<String> = DSL.field("email", String::class.java)
val PASSWORD: Field<String> = DSL.field("password", String::class.java)
}
}
Run Code Online (Sandbox Code Playgroud)
关注
data class Followers(
val id: String,
val followerId: String,
val userId: String
) {
companion object {
val TABLE: Table<Record> = DSL.table("followers")
val ID: Field<String> = DSL.field("id", String::class.java)
val FOLLOWER_ID: Field<String> = DSL.field("follower_id", String::class.java)
val USER_ID: Field<String> = DSL.field("user_id", String::class.java)
}
}
Run Code Online (Sandbox Code Playgroud)
当我做了一些简单的SQL语句并且它工作得很好时,但是当我尝试下一个语句时,我得到了异常.
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)
Run Code Online (Sandbox Code Playgroud)
此代码的预期声明是:
select *
from user u
right outer join followers f
on u.id = f.follower_id
where u.id = 'e30919bf-5f76-11e8-8c96-701ce7e27f83';
Run Code Online (Sandbox Code Playgroud)
但是我从这段代码中得到的陈述是:
select *
from user
right outer join followers
on id = follower_id
where id = 'e30919bf-5f76-11e8-8c96-701ce7e27f83'
Run Code Online (Sandbox Code Playgroud)
当然,这给了我(理所当然)where子句中的错误 列'id'是不明确的
它提出了几个问题:
select不能转换为正确的SQL语句?我做错了什么?Luk*_*der 15
我似乎太复杂了,最终无法维持.所以,我决定创建自己的表模型(类似于hibernate的工作原理).
你(可能)走下了痛苦和苦难的漫长道路.首先,您现在需要考虑数据库迁移,最好使用数据库的DDL语言.这意味着,从长远来看,您的数据数据库模型应该比您的客户端模型更重要.实际上,您的客户端模型是数据库模型的副本,而不是您想要独立维护的内容.有了这种心态,让代码生成器从数据库模型生成客户端模型更合理,反之亦然.
当然,当你启动一个项目时,Hibernate也会使客户端的第一个方法变得容易.然而,一旦你去生产,你将不得不迁移你的数据库,然后这个模型将破裂.你首先回到数据库,现在已经值得设置.
所以不行.代码生成现在可能会引入一些复杂性,但是与您创建自己的表模型相比,它将更容易维护.
Run Code Online (Sandbox Code Playgroud)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)该代码的预期声明是:[...]
嗯,这取决于什么u和f是什么.你不能只是将你的Kotlin引用重命名为你的表,并期望jOOQ知道它们的含义.即你可能创建了如下引用:
val u = User.TABLE;
val f = Follower.TABLE;
Run Code Online (Sandbox Code Playgroud)
如果这就是你创建引用的方式,那么这两个东西在身份上是相同的.jOOQ并没有神奇地对你的Kotlin代码进行反向工程,以发现你想要对你的表进行别名.你必须告诉jOOQ:
val u = User.TABLE.as("u");
val f = Follower.TABLE.as("f");
Run Code Online (Sandbox Code Playgroud)
但是现在你还没有完成.您User.TABLE使用普通SQL API构造了引用,这意味着jOOQ的运行时不知道该表中的列.您不能再从别名表引用这些列,因为纯SQL表的Table<?>别名表的类型不是User.
当然,您可以创建TableImpl实例并在实例中注册所有列TableImpl- 就像代码生成器一样.在这种情况下,您将拥有与它们关联的表和列,并且即使使用别名表也可以使用它们安全地键入.
所有这些东西都是由生成的代码自动处理的,我建议你再次使用jOOQ.任何人都不会将代码生成器与jOOQ一起使用的主要原因是因为数据模型是动态的,即在编译时不知道.否则,您只需要自动重复代码生成器已为您完成的大量工作.而且,如前所述,当您开始迁移架构时,您将在以后做更多工作.
| 归档时间: |
|
| 查看次数: |
2544 次 |
| 最近记录: |