【问题标题】:How do I prevent Hibernate from deleting child objects not present in a JSON post?如何防止 Hibernate 删除 JSON 帖子中不存在的子对象?
【发布时间】:2016-10-07 11:38:58
【问题描述】:

我有一个 JPA Property 实体,它有孩子(多个 Rate 和多个 Reservation)。在我的 JavaScript 应用程序中,我通过 REST {property:{rates:[...], reservations[...]} 拉动 JSON。 Rates and Reservations 非常冗长,所以当我发布属性更新(比如更改名称)时,我会从JSON POST 有效负载中删除rates 和reservations。我希望 Hibernate 会简单地忽略丢失的键,但是,它正在删除所有保存的孩子。如果它们不存在,我如何指定 Hibernate 忽略它们?

@Entity
public class Property {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    String name;

    @OneToMany(mappedBy = "property", cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
    @JsonManagedReference
    private Set<SeasonRate> rates = new HashSet<>();

    @OneToMany(mappedBy = "property", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
    private Set<Reservation> reservations = new HashSet<>();

}

Ps:我对级联的理解有限,但我确实想要这样的功能,即如果有人删除一个属性,它必须删除费率和预订。不过,我无法通过完整的属性保存来更新价格或预订,所以也许我应该只使用 CASCADE=UPDATE?价格有自己的更新机制,预订也有。

【问题讨论】:

  • JSON 如何解组到实体?
  • @AlanHay,在 Spring Boot 中使用默认的 Jackson Marshaller

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


【解决方案1】:

迟到的答案,但是如果您使用 Spring MVC Rest 控制器而不是 Spring Data Rest 控制器来处理更新,那么看起来前者不支持部分更新/补丁请求。

使用通过表单直接修改实体的传统非 RESTful Web 应用程序当然是可能的。例如:

@RequestMapping
public String updateEntity(@ModelAttribute myEntity){
  //submitted form parameters merged to existing entity 
  //loaded via getMyEntity() leaving unmodified fields as they were
}

@ModelAttribute
public MyEntity getMyEntity(){
  //load some existing entity
} 

但是,当通过 @RequestBody 将 JSON 绑定到实体时,这是不可能的:

@RequestMapping
public String updateEntity(@RequestBody myEntity){
  //new instance instantiated by the Jackson mapper
  //missing fields will be null
}

围绕这个有一些出色的 JIRA:

https://jira.spring.io/browse/SPR-13127

https://jira.spring.io/browse/SPR-10552

https://jira.spring.io/browse/SPR-13127

以及各种 SO 问题:

Spring Partial Update Object Data Binding

不过,好消息是 Spring Data Rest 确实支持通过补丁进行部分更新,因此如果可以选择将存储库公开为 Rest 存储库,那么您应该能够实现所需的行为:

https://spring.io/guides/gs/accessing-data-rest/

PUT 替换整个记录。未提供的字段将被替换 与空。 PATCH 可用于更新项目子集

【讨论】:

    猜你喜欢
    • 2018-07-30
    • 1970-01-01
    • 1970-01-01
    • 2021-05-22
    • 2019-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-10
    相关资源
    最近更新 更多