【问题标题】:How to properly update entities using REST and JPA/Hibernate如何使用 REST 和 JPA/Hibernate 正确更新实体
【发布时间】:2018-04-24 15:37:02
【问题描述】:

我有实体 Document,它有很多列,与其他一些实体进行一对一、一对多和多对多的映射。

例子:

Document:
  id,
  title,
  body,
  authors,
  viewers,
  ...

使用 REST,我想更新一些特定的文档,控制器接收序列化的 Document 对象,调用 EntityManager 的合并方法将 null 结果保存到数据库,如果控制器仅接收到 body ,那么我希望只更新正文,但合并删除标题、作者和查看者等记录。

我知道这是 EntityManager 的标准行为,但我想知道在不从前端或其他端点接收整个实体的情况下,对实体进行更新的最优选技术是什么。我应该使用收到的 id 从数据库加载实体并手动设置所有字段,然后保存到数据库,还是应该使用其他技术。

手动编写所有设置器来复制更改我没有任何问题,但是实体的大小确实很大,有很多关系。在这种情况下寻求最佳实践。

我了解 DTO,但在将实体用于控制器和服务方法时,我想要另一种方法。

【问题讨论】:

  • 您可以使用 em.merge 更新 Java 实体中的特定字段(这通过 JPA),或者您可以编写一个 SQL 更新语句来为您执行此操作。基本上,JPA 是一个通过实体管理器的抽象层,位于对关系数据库的 SQL 访问之上。

标签: java spring hibernate rest jpa


【解决方案1】:

对于实体部分更新,您将需要使用条件 api 或 jpql ...更新然后再次插入....您还可以将updatable=false 用于仅应在创建时设置的列(例如CREATION_DATE),并且休眠中还有一个不错的功能,称为@DynamicUpdate,但我没有尝试过看起来很棒...它只更新修改后的字段(check Vlad's post here)...关于 DTO DP,如果您想隐藏/修改来自客户端的某些数据,无论您存储的方式如何,您可能总是需要使用数据......而且它始终是分离关注点的好方法(但伴随着域和 DTO 对象之间的映射问题,这要归功于spring converters

【讨论】:

  • 我实际上决定坚持使用带有信息子集的 DTO,但在合并实体之前,我从数据库中加载它,然后使用我编写的简单通用对象映射器从 DTO 复制新值(我认为如果我需要更复杂的东西,我稍后会切换到弹簧转换器)。对我来说似乎足够了,但不确定......
【解决方案2】:

有两种选择,一种是更新查询,效果很好,但您可能会觉得 您正在失去一些休眠功能和代码的简单性。否则,您可以像下面这样以休眠方式进行操作

   AuditorBean auditorBean = (AuditorBean) session.get(AuditorBean.class, AuditorBean.getId());
    auditorBean.setFirstName("aa");
    auditorBean.setLatName("bb");
    auditorBean.setTrainLevel("ISO");
    auditorBean.setAccessLevel(4);

在这里你不应该调用像 saveOrUpdate() 或 merge() 这样的方法。 对象与事务关联,因此对象会在事务结束时自动刷新并提交。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多