如何在DDD中实现Vaughn Vernon关于聚合中引用的建议

时间:2016-04-26 10:40:27

标签: jpa domain-driven-design spring-data-jpa

遵循Vaughn Vernon在DDD中关于聚合中引用的建议

  

让聚合按ID(标识)引用其他聚合,而不是聚合本身。

如何用JPA和Hibernate 4.3.11.Final来完成这个?

我尝试使用this example

这样的东西
@Entity
public class OrdenItem implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne(targetEntity = Orden.class, optional = false)
    private Long ordenId;

    @ManyToOne(targetEntity = Product.class, optional = false)
    private Long productId;
    .
    .
    .

但是当我尝试用Spring Data检索一些实例时

@Query("" 
        + " SELECT b " 
        + " FROM  OrdenItem b "
        )
List<OrdenItem> findByYYYY();

出现以下错误

  

java.lang.IllegalArgumentException:无法将java.lang.Long字段com.aggregates.model.OrdenItem.ordenId设置为com.aggregates.model.Orden   at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)〜[na:1.8.0_51]   at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)〜[na:1.8.0_51]   at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:81)〜[na:1.8.0_51]

我知道如果我将代码更改为

,这是有效的
@ManyToOne
private Orden orden;

@ManyToOne
private Product product;

但我想遵循Vaughn Vernon的推荐

1 个答案:

答案 0 :(得分:1)

乘坐

@ManyToOne(targetEntity = Product.class, optional = false)

并将orderId和productId保存为表中的数字。

@Column(name="PRODUCT_ID")

那就是它。

如果您想获得包含其商品的订单,然后获得字符串表示,则需要产品名称,以及我认为您要为每个订单商品检索产品的位置。 请允许我说这是Vaughn会做的事情: 首先,我根本不需要通过其标识符orderId保存从OrderItem到Order的引用,因此您可以安全地删除它。从域服务中,您所做的只是检索订单聚合根以及聚合的项集合。而不是让每个项目都持有productId,我会改变它以使每个orderItem保持我的产品的另一个概念身份,它必须是产品SKU或其他东西,你也可以保持其名称,就像它&#39;在现实世界中的秩序。无论如何,这些价值观根本没有变化,是不可改变的。

塞巴斯蒂安。