jpa - 将Kotlin不可变实体与JPA一起使用时发生意外更改

标签 jpa kotlin

在我们的项目中,我们将kotlin与JPA结合使用。我们所有实体都是不可变的,因此无法直接设置我们实体的字段。您必须使用copy方法创建一个新实例。如果要将这些更改反射(reflect)到数据库中,则必须使用显式函数调用来持久保存此新创建的实体。

从一开始,这种方法对我们来说就是完美的。但是,如今我们遇到了一些问题,例如某些实例在内存中发生了意外更改。

val instance1 = repository.findById(entityId)
repository.save(instance1.copy(deletedAt = Instant.now()))
..
..
assertNull(instance1.deletedAt())

在上面的代码片段中,从数据库中检索instance1,并使用copy方法设置instance1的deleteAt字段,并将使用此copy方法创建的新实例传递到存储库的save方法。我们没有设置instance1的任何字段,而是创建一个新实例来进行这些更改。但是,断言行上的结果意外地为非空。

看来,JPA持久性上下文(一级缓存)与kotlin的不可变和复制方法逻辑存在冲突。

使用JPA和不可变的Kotlin实体时,有人遇到这个问题,任何建议或最佳做法吗?

最佳答案

我怀疑问题是您忽略了save()的返回值。它的文档说:

Saves a given entity. Use the returned instance for further operations as the save operation might have changed the entity instance completely.



但是你不是那样做的。相反,您将继续使用可能已经更改的原始实例(如上所述)。

而是存储save()的返回值,然后使用它。 (通过将instance1设置为var,或创建新的val,然后不引用instance1。)

(这不是Kotlin特有的问题,在Java中完全相同.JPA,Spring和c通过融合字节码来发挥其魔力,因此可以做代码无法做的事情-例如更改不可变值。您可以忽略它,但是这种情况很明显。)

关于jpa - 将Kotlin不可变实体与JPA一起使用时发生意外更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54072737/

相关文章:

java - Spring JPA 映射 - 第一步

spring - 如何配置spring批处理不自动创建用于存储元数据的批处理表?

collections - Kotlins扩展方法Stream.toList()丢失

tomcat - 使用 Tomcat + JPA + Hibernate 时出错

java - JPA:处理复制的列表也会修改 ParentCollection

json - Moshi + Kotlin + SealedClass

android - Coordinatorlayout adjustResize 打开键盘时不折叠工具栏

kotlin - 无法在 kotlin 多平台中访问预期的类构造函数参数

kotlin - Kotlin 文档中的术语 "Changing type from unsigned type to signed counterpart (and vice versa) is a binary incompatible change"是什么意思?

java - 在多线程 RMI 架构中使用 JPA