域驱动设计中的实体

时间:2012-02-24 09:35:51

标签: java java-ee domain-driven-design

我正在阅读Eric Evans关于DDD的书,我对以下引用有疑问。如果不使用属性,如何制作equals()方法?我正在使用JPA,并且我有一个唯一的id属性,但在实际持久保存实体之前不会设置。所以你会怎么做?我已经基于属性实现了equals方法,并且我理解为什么你不应该因为它在我的项目中失败。

关于实体的部分:

  

当一个对象通过其身份而不是它的身份来区分时   属性,使其主要在模型中定义。保持   类定义简单,注重生命周期的连续性和   身份。定义一种区分每个对象的方法,无论如何   它的形式或历史。警惕要求匹配的要求   对象按属性。定义一个保证的操作   为每个对象产生一个独特的结果,可能是通过附加一个   保证唯一的符号。这种识别方式可以   来自外部,或者它可能是由...创建的任意标识符   对于系统,但它必须对应于身份   模型中的区别。模型必须定义它意味着什么   同样的事情。

http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215

4 个答案:

答案 0 :(得分:2)

夫妻接近可能:

  • 使用商家密钥。这是最“符合DDD”的方法。仔细查看域和业务要求。例如,您的企业如何识别客户?他们使用社会安全号码还是电话号码?如果它是基于纸张的(没有计算机),您的企业将如何解决这个问题?如果没有自然业务密钥,请创建代理。选择最终的商家密钥,并在equals()中使用它。 DDD书中有一节专门讨论这个具体问题。

  • 对于没有自然业务键的情况,您可以生成UUID。这在分布式系统中也具有优势,在这种情况下,您不需要依赖集中(并且可能不可用)的资源(如数据库)来生成新的ID。

  • 还可以选择依赖默认equals()实体类。它会比较两个内存位置,在大多数情况下就足够了,因为Unit Of Work(Hibernate Session)保留所有实体(这个ORM模式称为Identity Map)。这是不可靠的,因为如果你使用不限于一个Hibernate会话范围的实体(想想线程,分离的实体等)它会破坏

有趣的是,'官方'DDD示例使用了一个非常轻量级框架,其中每个实体类都是使用一种方法从Entity接口派生的:

boolean sameIdentityAs(T other) 
// Entities compare by identity, not by attributes.

答案 1 :(得分:1)

如果对象尚未持久化,那么根据属性比较2个对象是否有任何伤害?

我不确定为什么这会在你的项目中失败,但根据我的经验,如果你的属性不是最终的,那么基于属性的比较几乎总是很滑。这意味着,现在相同的2个对象在某些时候可能不相等。这真是太糟了。

鉴于大多数Java类与其访问器一起编写,等于比较属性被认为是一个坏主意。

但是,我可能首先检查ID字段是否为空。如果它为null,我会回到属性比较。如果它不为null,那么只需使用它而不做其他任何事情。这有意义吗?

答案 2 :(得分:1)

给定Person类包含属性namesurname。当21岁的人更改其名称时,它仍然是同一个人(等于给出true)? 如果你在属性上写等于基础,那么,它就不是同一个人,所以在我看来,最好的方法是在它们的业务标识符上测试实体的相等性(在整个实体生命周期中是唯一的和不可变的)。

答案 3 :(得分:0)

另一种解决方案可能是在您的实体中使用UUID字段。

在这种情况下,您可以使用UUID作为主键或仅使用等号。

@Entity
public class YourEntity{ 

    @Id
    private String uuid = UUID.randomUUID().toString();

    // getter only...

}
相关问题