【发布时间】:2020-08-15 20:51:16
【问题描述】:
在我参与的一个DDD-项目中,我们正在寻找一些方便的解决方案,将entity objects 映射到domain objects,反之亦然。
该项目的开发人员同意将域模型与数据模型完全分离。
数据层使用JPA (Hibernate)作为持久化技术。
我们都认为持久性是 DDD 中的一个实现细节,从开发人员的角度来看,我们都在为应用程序的各个方面寻找最合适的解决方案。
我们最担心的是,当一个包含entities 列表的aggregate 映射到一个JPA entity 时,它又包含一个one-to-many 关系。
看看下面的例子:
领域模型
public class Product extends Aggregate {
private ProductId productId;
private Set<ProductBacklogItem> backlogItems;
// constructor & methods omitted for brevity
}
public class ProductBacklogItem extends DomainEntity {
private BacklogItemId backlogItemId;
private int ordering;
private ProductId productId;
// constructor & methods omitted for brevity
}
数据模型
public class ProductJpaEntity {
private String productId;
@OneToMany
private Set<ProductBacklogItemJpaEntity> backlogItems;
// constructor & methods omitted for brevity
}
public class ProductBacklogItemJpaEntity {
private String backlogItemId;
private int ordering;
private String productId;
// constructor & methods omitted for brevity
}
存储库
public interface ProductRepository {
Product findBy(ProductId productId);
void save(Product product);
}
class ProductJpaRepository implements ProductRepository {
@Override
public Product findBy(ProductId productId) {
ProductJpaEntity entity = // lookup entity by productId
ProductBacklogItemJpaEntity backlogItemEntities = entity.getBacklogItemEntities();
Set<ProductBacklogItem> backlogItems = toBackLogItems(backlogItemEntities);
return new Product(new ProductId(entity.getProductId()), backlogItems);
}
@Override
public void save(Product product) {
ProductJpaEntity entity = // lookup entity by productId
if (entity == null) {
// map Product and ProductBacklogItems to their corresponding entities and save
return;
}
Set<ProductBacklogItem> backlogItems = product.getProductBacklogItems();
// how do we know which backlogItems are: new, deleted or adapted...?
}
}
当ProductJpaEntity 已经存在于DB 中时,我们需要更新所有内容。
如果有更新,ProductJpaEntity 已经在 Hibernate PersistenceContext 中可用。
但是,我们需要弄清楚哪些ProductBacklogItems 被更改了。
更具体地说:
-
ProductBacklogItem可以添加到Collection -
ProductBacklogItem可能已从Collection中删除
每个ProductBacklogItemJpaEntity 都有一个Primary Key 指向ProductJpaEntity。
似乎检测新的或删除的ProductBacklogItems 的唯一方法是通过Primary Key 匹配它们。
但是,主键不属于域模型...
还有可能首先删除ProductJpaEntity 的所有ProductBacklogItemJpaEntity 实例(存在于数据库中),刷新到数据库,创建新的ProductBacklogItemJpaEntity 实例并将它们保存到数据库。
这将是一个糟糕的解决方案。每次保存 Product 都会导致 DB 中出现多个 delete 和 insert 语句。
有哪些解决方案可以解决这个问题,而不会对领域和数据模型做出太多牺牲?
【问题讨论】:
-
你的
ProductBacklogItemJpaEntity应该是一个@Entity拥有自己的@PrimaryKey,然后当你收到Product时,只需将ProductBacklogItem列表转换为ProductBacklogItemJpaEntity列表设置它进入ProductJpaEntity并保存。当您调用存储库save方法时,如果Product域对象中的列表包含所有积压项目,则此方法有效(剧透,这是必须的)。如果这不是您的情况,则需要有关何时使用save方法的一些详细信息才能做出响应。
标签: java jpa domain-driven-design ddd-repositories