【问题标题】:Spring Data CrudRepository only returns changed fields when calling save()Spring Data CrudRepository 仅在调用 save() 时返回更改的字段
【发布时间】:2018-10-17 19:01:10
【问题描述】:

我正在使用 Spring Data(版本 1.13.9.RELEASE)并且有一个名为 myRepositoryCrudRepository。我正在调用myRepository.save(myObject),以覆盖数据库中myObject 的现有实例,并将myObject 的某些字段指定为null

例如:

{
    "prop1": "val1",
    "prop2": null,
    "prop3": "val3"
}

当我调用myRepository.save(myObject) 并读取返回值时,我设置为nullmyObject 的所有字段都返回为null(本例中为prop2)。

但是,在调用save() 之后,数据库中prop2 的值不是null - 它仍然是我调用save() 之前的值。

这实际上是我在这种特殊情况下想要的行为(在调用 myRepository.save() 时忽略 null 值),但我希望 save() 的返回值能够反映之后数据库中的实际情况操作,而不是只返回更新后的字段并将指定为null 的字段设置为null 或其默认值(例如布尔值的false

这是CrudRepositorysave() 行为的预期行为吗?

【问题讨论】:

  • 只是好奇您的数据库是否正确更新?
  • 有可能不是。我正在使用 DynamoDB。可能应该将字段设置为null。但是,如果不是,我认为CrudRepository 在调用save() 以返回最新值时基本上应该重新查询数据库。我不确定它在哪里将这些值视为null(因为它们不是 Dynamo 中的null
  • 第二个问题..你在用Hibernate吗?
  • @PranjalGore 是的,我是
  • 好的。因此,您需要首先获取最新的对象,这会将对象附加到持久状态。其次,更新对象(虽然它仍处于持久状态),然后最后调用 save.

标签: java spring spring-data


【解决方案1】:

要理解这个问题,你需要对 Hibernate Object Lifecycle 有一点了解。

休眠对象生命周期由以下状态组成: 1. 瞬态 2. 持久状态 3. 分离状态等

当您创建一个新对象时,它处于瞬态,而 Hibernate 无法检测在瞬态中存在/创建的对象。

当您调用 save() saveOrUpdate() 时,对象会从瞬态状态移动到持久状态,现在 Hibernate 将开始跟踪对对象所做的所有更改(但对象尚未写入数据库) .

因此,在您的情况下,由于对象未处于持久状态,因此休眠无法识别它并会触发(很可能)insert 查询。但是,如果对象已经处于持久状态,hibernate 会知道某些字段已被修改,因此会触发 update 查询。

因此,如果您希望 hibernate 触发 update 查询,您需要确保对象处于持久状态。

【讨论】:

    【解决方案2】:

    这意味着事务还没有完成,所有的变化都只在缓存中。要强制更新,您可以调用 entityManager.flush() 或将您需要的所有逻辑移动到另一个 Service 或 Manager 的单独公共方法中,并将其注释为 @Transactional

    【讨论】:

      猜你喜欢
      • 2018-08-15
      • 1970-01-01
      • 2020-03-26
      • 2016-03-29
      • 1970-01-01
      • 1970-01-01
      • 2015-08-04
      • 2015-11-13
      • 1970-01-01
      相关资源
      最近更新 更多