Kotlin数据类的equals()方法是否可以在没有进一步修改的情况下与JPA结合使用?

Kotlin有一个Data类,包含toString(), equals(), hashCode(), and copy()

可以使用equals() and hashCode()直接开箱即用,而无需进一步调整JPA类? 我们通常不得不在下面链接的文章中花费大量时间阅读“自然键”,持久化上下文生命周期等,然后再确信我们做的是正确的事情:

  • 等于和哈希码
  • 在-JPA的哈希码,等于-困境

我们现在可以简单地依靠Kotlin的equals() and hashcode()实现吗?

在我看来,不应该使用Kotlin中的数据类,除非你真的明白你在做什么。

在可变数据上覆盖equals / hashCode会导致一个问题。 考虑你已经添加了一个可变类的实例到HashSet ,然后改变了一些,如果该实例的属性。 这会影响hashCode返回的值。

反过来,这使HashSet找不到实例,因为它将在完全不同的哈希表条目中查找它。 你将无法从HashSet移除这个实例!

在kotlin中作为数据类的候选者的好例子是:复数,恒定大小的向量。 不好的例子是:JPA实体,DTO。

至于JPA,这些文章是有自己的见解的。 还有一种观点:你不应该为JPA实体重写equalshashCode

理由:JPA提供者(Hibernate,EclipseLink) 必须保证a === b iff a和b在表中具有相同的主键,并且a和b都处于持久状态。 这个合同可能会被拆分实体。 但是,在我看来,与分离实体合作是一个不好的做法,应该避免。 唯一可能有意义的是存储分离的实体将它们合并到另一个JPA事务中。

JPA实体应该依赖于对象身份,而不是主键相等 – 这大概是对象关系映射的全部内容的90%。 有一个JPA实现跳过各种循环来创建,维护和传播身份映射 ,然后忽略它可能是一个标志,你根本不需要JPA,并会导致问题。 特别是如果你不是100%知道你在做什么。

也就是说,在很多情况下你可以使用Kotlin数据类,只要:

  • 您不会将持久对象存储在地图和集合中
  • 你保留默认的构造函数,不要尝试以任何方式触摸对象初始化(提供默认值等)