当前位置: 首页 > 面试题库 >

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

戴树
2023-03-14
问题内容

我正在使用jOOQ和Kotlin进行实验,并看到了一些教程和文档,看起来非常不错。

但是,如果使用jOOQ感到非常烦人,则会生成代码。它似乎太复杂了,最终无法维护。我决定创建自己的表模型(类似于休眠方式)。

我创建了两个表模型:

用户

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)
    }
}

追随者

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)
    }
}

当我执行一些琐碎的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)

该代码的预期语句为:

select *
from user u
right outer join followers f
on u.id = f.follower_id
where u.id = 'e30919bf-5f76-11e8-8c96-701ce7e27f83';

但是我从这段代码中得到的语句是:

select *
from user
  right outer join followers
  on id = follower_id
where id = 'e30919bf-5f76-11e8-8c96-701ce7e27f83'

当然,这会正确地告诉我 where子句中 的错误 列’id’

它提出了一些问题:

  1. 有没有更好的方法来声明表模型而无需代码生成。
  2. 为什么DSLselect无法转换为正确的SQL语句?我做错了什么?

问题答案:

首先,关于不愿使用代码生成的一些建议:

我似乎太复杂了,最终无法维持。因此,我决定创建自己的表模型(类似于休眠方式)。

您(很可能)要经历很长的痛苦和磨难。首先,您现在已经需要考虑数据库迁移,最好使用数据库的DDL语言来完成。这意味着,从长远来看,数据的数据库模型对您而言应该比客户端模型更为重要。实际上,您的客户端模型是数据库模型的副本,而不是您想要独立维护的东西。有了这种思想,让代码生成器从数据库模型生成客户端模型更为合理,反之亦然。

当然,在启动项目时,Hibernate也使客户端优先方法也变得容易。但是,一旦投入生产,您
不得不迁移数据库,然后此模型将崩溃。您首先要返回数据库,现在已经值得进行所有设置。

所以不行。 现在 ,代码生成可能会带来一些复杂性,但是与创建自己的表模型相比 ,维护 代码将 更加容易

我在这里撰写了一篇有关该主题的更长的博客文章。

关于您的具体问题:

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)

该代码的预期语句为:[…]

好吧,这取决于什么uf是什么。您不能只是将Kotlin引用重命名为表并期望jOOQ知道它们的含义。也就是说,您可能按如下方式创建了引用:

val u = User.TABLE;
val f = Follower.TABLE;

如果那是您创建引用的方式,那么根据身份,这两件事就是 同一件事 。jOOQ不会神奇地对您的Kotlin代码进行逆向工程以发现您要对表进行 别名
。您必须告诉jOOQ:

val u = User.TABLE.as("u");
val f = Follower.TABLE.as("f");

但是现在您还没有完成。您User.TABLE使用简单的SQL
API
构造了引用,这意味着jOOQ的运行时不了解该表中的列。您无法再从别名表中引用这些列,因为普通SQL表的Table<?>别名表的类型为,而不是User

当然,您可以创建TableImpl实例并在实例中注册所有列TableImpl-就像代码生成器一样。在这种情况下,您将具有与之关联的表
列,并且即使使用别名表也可以安全地使用它们。

所有这些东西都是由生成的代码自动处理的,我再次建议您将其与jOOQ一起使用。任何人都不将代码生成器与jOOQ一起使用的主要原因是因为数据模型是动态的,即在编译时未知。否则,您将自动重复代码生成器已经为您完成的大量工作。而且,如前所述,当您开始迁移架构时,您将在以后做更多的工作。



 类似资料:
  • 我使用了Jooq官方网站上的这个工具:https://github.com/etiennestuder/gradle-jooq-plugin从我的数据库生成代码。 但如果我设置

  • 我有一个有许多表的数据库。我想开始使用jOOQ为我的应用程序。但是我不希望JOOQ为所有表生成代码,但只为表的一小部分生成代码。我如何配置它?

  • 我更改了数据库中的一些表,所以我想生成记录、键、类等。但是每次我这样做时,它总是跳过jooq代码生成。 [INFO]--jooq-codegen-maven:3.11.10:generate(默认cli)@http网关--[INFO]跳过jooq代码生成 为了运行Jooq代码生成,我应该执行哪个mvn cmd?现在我使用: 谢谢

  • 关于StackOverflow有一些关于如何处理期货列表的建议,但我想尝试我自己的方法。但是我无法编译以下代码 我有一份未来的清单。我想数一数他们中有多少人及格或不及格。我应该得到(2,1),我将其存储在一个元组中。我想采取的方法是遍历列表中的每个元素。列表的元素是Future[Int]。对于每个元素,我调用flatMap,它调用下一个递归循环(我假设如果调用flatMap,那么特定的未来将是成功

  • 本文向大家介绍手写代码:合并有序数组相关面试题,主要包含被问及手写代码:合并有序数组时的应答技巧和注意事项,需要的朋友参考一下 参考回答: 解法一:从结尾开始归并,不会覆盖元素。从A[n+m-1]处开始往前一个元素一个元素的求,每次都要比较A[i]和B[j]的大小。需要注意的是,要考虑到: A和B有一个为空时的情况 解法二:由于合并后A数组的大小必定是m+n,所以从最后面开始往前赋值,先比较A和B

  • 我使用jOOQ程序代码生成数据库,但现在我遇到了一些问题。在数据库中,我有表A和表B。第一次都生成了pojo、dao、接口等。经过一段时间的开发,我发现表A需要添加一些字段或修改一些字段,所以我不得不再次编码,然后jOOQ代码生成器将覆盖现有的代码,这让我很难过。当我在排除表的情况下使用“排除A”时,发现只生成了表A的数据,表B将被删除。我不知道如何处理这个问题。我的代码生成器如下: