Java Spring数据Rest-如何防止对聚合根的子实体进行PUT/PATCH更新

Java Spring数据Rest-如何防止对聚合根的子实体进行PUT/PATCH更新,java,spring,domain-driven-design,spring-data-rest,spring-hateoas,Java,Spring,Domain Driven Design,Spring Data Rest,Spring Hateoas,我正在构建一个基于SpringDataREST/SpringHateOAS的应用程序,并试图遵循这里(以及其他地方)概述的DDD原则: 特别是聚合和复杂状态的概念通过专用资源发生变化 还应避免使用HTTP修补程序或PUT进行业务域的(复杂)状态转换,因为您遗漏了许多与触发此更新的实际业务域事件相关的信息。例如,更改客户的邮寄地址是向新的“ChangeOfAddress”资源发送的邮件,而不是具有不同邮寄地址字段值的“customer”资源的补丁或PUT 我正在努力解决的是一种在允许对聚合根进行

我正在构建一个基于SpringDataREST/SpringHateOAS的应用程序,并试图遵循这里(以及其他地方)概述的DDD原则:

特别是聚合和复杂状态的概念通过专用资源发生变化

还应避免使用HTTP修补程序或PUT进行业务域的(复杂)状态转换,因为您遗漏了许多与触发此更新的实际业务域事件相关的信息。例如,更改客户的邮寄地址是向新的“ChangeOfAddress”资源发送的邮件,而不是具有不同邮寄地址字段值的“customer”资源的补丁或PUT

我正在努力解决的是一种在允许对聚合根进行外观更改的同时强制执行此操作的方法

使用此简化示例:

@Entity
public class Customer
{
   private @Id @GeneratedValue(strategy = GenerationType.AUTO) Long id;

   private String name;

   private String comment;

   @Access(AccessType.PROPERTY)
   @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
   private Set<Address> addresses = new HashSet<>();

   ... getters and setters

    public void addAddress(Address address)
    {
        addresses.add(address);
        ... custom code to raise events etc
    }
}

public interface Customer extends CrudRepository<Customer, Long>
{
}
@实体
公共类客户
{
private@Id@GeneratedValue(strategy=GenerationType.AUTO)长Id;
私有字符串名称;
私有字符串注释;
@访问权限(AccessType.PROPERTY)
@OneToMany(cascade=CascadeType.ALL,orphan=true)
私有集地址=新HashSet();
…能手和二传手
公共无效地址(地址)
{
地址。添加(地址);
…用于引发事件等的自定义代码
}
}
公共接口客户扩展Crudepository
{
}
允许外观更改(例如更新注释)但防止直接更新子集合的更改的最佳/正确方法是什么

如果有人试图修改子集合,让setter抛出异常,我唯一能想到的就是这样做。

@Entity
@Entity
public class Customer
{
   private @Id @GeneratedValue(strategy = GenerationType.AUTO) Long id;

   private String name;

   private String comment;

   @JsonProperty(access = JsonProperty.Access.READ_ONLY)
   @Access(AccessType.PROPERTY)
   @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
   private Set<Address> addresses = new HashSet<>();
}
公共类客户 { private@Id@GeneratedValue(strategy=GenerationType.AUTO)长Id; 私有字符串名称; 私有字符串注释; @JsonProperty(access=JsonProperty.access.READ_ONLY) @访问权限(AccessType.PROPERTY) @OneToMany(cascade=CascadeType.ALL,orphan=true) 私有集地址=新HashSet(); }
祝贺您,您刚刚在SDR中碰到了一个米深的凹坑。您可以在映射时阻止请求读取数据。如果您正在使用Jackson,请使用
@JsonProperty(access=JsonProperty.access.READ_ONLY)标记您的子集合
。所以这个字段只允许被服务,但不允许更新。@BogdanOros感谢这很好,如果你把它作为一个答案,我会接受它。@chrylis我不认为这一定是SDR的缺点,如果我使用Spring mvc/hateoas并手工编写控制器,我仍然会遇到同样的问题。问题更多来自于试图实现聚合模式。再次感谢@Bogdan Oros。如果至少有一个SpringDataREST示例涵盖了这一点,那就太好了。这似乎是应用聚合模式时的一个主要考虑因素。