【问题标题】:JpaRepository getOne() fetches and updates whole objectJpaRepository getOne() 获取并更新整个对象
【发布时间】:2021-06-08 18:05:29
【问题描述】:

我正在尝试模仿这个公认的 SO 答案 https://stackoverflow.com/a/39746931/3214777 在仅更新某些对象的字段时使用 Hibernate 代理。 我的代码如下:

  @Transactional
public void updateStudentYear(int uniqueNumber, int newYear) {
    Student studentProxy = studentRepository.getOne(uniqueNumber);
    studentProxy.setYear(newYear);
    studentRepository.save(studentProxy);
}

问题在于 Hibernate 同时进行了完全选择完全更新。以下是日志:

2021-03-10 20:24:23.240 DEBUG 118757 --- [main] org.hibernate.SQL:选择 student0_.unique_number 作为 unique_n1_1_0_,student0_.name 作为 name2_1_0_,student0_.team 作为 team3_1_0_,student0_.year 作为year4_1_0_ 来自学生 student0_ where student0_.unique_number=?

2021-03-10 20:24:23.268 DEBUG 118757 --- [main] org.hibernate.SQL:更新学生集 name=?, team=?, year=? unique_number=?

我原以为只会发布一个“更新年份”声明,但令我惊讶的是,看起来一切都像经典的 findOne()/save() 对操作一样完成。我错了吗?

【问题讨论】:

  • 它只会延迟选择的执行,可能是因为你没有启用部分更新它仍然是一个完整的更新。接受的答案是错误的答案(如果您阅读 cmets,您也会注意到)。
  • @M. Deinum 那么我该如何启用部分上传?
  • 部分上传与部分更新有什么关系?如果您只想要部分更新,您可以在您的实体上使用 Hibernate 中的 @DynamicUpdate 注释。它只会对修改后的字段发出更新查询。
  • 我的意思是部分更新,抱歉。 '这是一个错字。
  • @DanielPop 部分更新并不总是一件好事,例如缓存。

标签: java spring hibernate proxy spring-data-jpa


【解决方案1】:

不,不幸的是,链接问题中的答案是错误的。 getOne()/getReference() 方法不是要更新单个字段,而是要避免访问数据库,除非需要。

该方法的用处在于

Foo foo = fooRepo.findOne(id);
Bar barProxy = barRepo.getOne(id);
foo.setBar(barProxy);
fooRepo.save(foo);

在这种情况下,Foo 将从数据库中获取,但Bar 不会。

JPA 将始终更新更新语句中的所有字段,尽管我不确定它是否会受到实现自己的dirty checking 的影响。 Hibernate 有 @DynamicUpdate 限制列,但 JPA 没有为其指定通用机制。

【讨论】:

    猜你喜欢
    • 2016-01-18
    • 2017-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多