持久化机制生成唯一标识
若从DB获取一个序列值(Sequence)或递增值,结果总是唯一。根据标识所需范围,数据库可生成2字节、4字节和8字节的唯一标识。在Java中的这些大小整数分别可表示
- 32,767
- 2,147,483,647
- 9,223,372,036,854,775,807
种不同标识值。
缺陷
性能。
从DB获取标识比APP生成慢得多。一种解决方法是将数据库序列缓存在APP,比如缓存在资源库。
这固然是一种好方法,但若服务器节点需重启,那么将失去很大一部分标识值区间。若丢失区间无法接受或只需相对较小标识值(2字节整数),这缓存机制便不实用,也没必要。当然可以找回丢掉的标识值区间,但可能引入新麻烦。
如果可使用延迟生成,那缓存标识便不是问题。以下是如何使用Hibernate和Oracle的序列来生成标识:
<id name="id" type="long" column="product_id"> <generator class="sequence"> <param name="sequence">product_seq</param> </generate> </id>
在采用MySQL的自增列时配置如下
<id name="id" type="long" column="product_id"> <generator class="native"/> </id>
这种方式的性能是很好的,同时配置Hibernate映射也是简单的。
3.1.3 另一个限界上下文提供唯一标识
若另一个限界上下文用于给实体标识赋值,那需要对每个标识进行查找、匹配和赋值。
最重要的是精确匹配。此时用户需提供一或多种属性,比如账户、用户名和E-mail地址,以精确定位需要匹配的结果。
通常匹配的输入是模糊的,导致多个查询结果,此时用户需要手动选择,如图
- 从外部系统中获取需要查找的唯一标识。用户界面中可显示唯一标识(本图),也可不显示
- 用户输入了模糊查找信息,通过调用外部限界上下文的API,返回的结果可能是0、1或多个匹配对象。接着用户要在结果中选择某特定对象。所选对象的身份标识将作为本地标识。外部实体的一些额外属性也可能被复制到本地实体。
- 缺陷
对象同步可能是个问题。外部对象的改变将如何影响本地对象?如何知道所关联的对象已经改变了呢?
可通过事件驱动架构和领域事件解决。本地限界上下文订阅外部系统中的领域事件,当本地上下文接收到外部系统的事件通知时,它将相应更新本地对象。有时同步事件可能由本地上下文发出,外部系统在接受到该事件时同样会做相应的更新操作。
要达到这样的目的并不容易,但这样做能够创建出更加具有自治性的系统。可将对象查找限定在本地对象中。这并不是说将外部对 象缓存在本地系统中,而是将外部概念翻译成本地限界上下文中的概念。
这是最为复杂的标识创建策略。要维护本地实体,我们不但需要考虑由本地 领域行为所导致的改变,还需要将外部系统也考虑在内。所以在使用这种策略时,应持保守态度。
参考
《实现领域驱动设计》