Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/339.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 聚合到JPA实体映射_Java_Jpa_Domain Driven Design_Ddd Repositories - Fatal编程技术网

Java 聚合到JPA实体映射

Java 聚合到JPA实体映射,java,jpa,domain-driven-design,ddd-repositories,Java,Jpa,Domain Driven Design,Ddd Repositories,在我参与的DDD-项目中,我们正在寻找一些方便的解决方案,将实体对象映射到域对象,反之亦然 该项目的开发人员同意将域模型与数据模型完全解耦。 数据层使用JPA(Hibernate)作为持久化技术 由于我们都认为持久性是DDD中的一个实现细节,从开发人员的角度来看,我们都在寻找应用程序各个方面最合适的解决方案 我们最大的担忧是,当一个包含实体列表的聚合映射到一个JPA实体时,该实体又包含一对多关系 请看下面的示例: 域模型 数据模型 存储库 类ProductJpaRepository实现Prod

在我参与的
DDD
-项目中,我们正在寻找一些方便的解决方案,将
实体对象
映射到
域对象
,反之亦然

该项目的开发人员同意将域模型与数据模型完全解耦。 数据层使用
JPA(Hibernate)
作为持久化技术

由于我们都认为持久性是DDD中的一个实现细节,从开发人员的角度来看,我们都在寻找应用程序各个方面最合适的解决方案

我们最大的担忧是,当一个包含
实体列表的
聚合
映射到一个
JPA实体
时,该实体又包含一对多关系

请看下面的示例:

域模型 数据模型 存储库

类ProductJpaRepository实现ProductRepository{
@凌驾
公共产品查找方式(ProductId ProductId){
ProductJpaEntity entity=//按productId查找实体
ProductBackLogitemJPAEEntity backlogItemEntities=entity.getBacklogItemEntities();
设置backlogItems=toBackLogItems(backlogItemEntities);
返回新产品(新产品ID(entity.getProductId()),backlogItems);
}
@凌驾
公共作废保存(产品){
ProductJpaEntity entity=//按productId查找实体
if(实体==null){
//将Product和ProductBackLogiItem映射到其相应的实体并保存
返回;
}
Set backlogItems=product.getProductBacklogItems();
//我们如何知道哪些备份项是:新的、删除的或修改的。。。?
}
}
DB
中已经存在
ProductJpaEntity
时,我们需要更新所有内容。 在进行更新时,
ProductJpaEntity
已在Hibernate
PersistenceContext
中可用。 但是,我们需要确定哪些
productbacklogitem
发生了更改

更具体地说:

  • ProductBacklogItem
    可能已添加到
    集合中
  • ProductBacklogItem
    可能已从
    集合中删除

每个
ProductBacklogItemJpaEntity
都有一个指向
ProductJpaEntity
主键。
似乎检测新的或删除的
productbacklogitem
的唯一方法是通过
主键来匹配它们。
但是,主键不属于域模型

还可以首先删除
ProductJpaEntity
的所有
ProductBacklogItemJpaEntity
实例(存在于数据库中),刷新到数据库,创建新的
ProductBacklogItemJpaEntity
实例并保存到数据库。 这将是一个糟糕的解决方案。
产品的每次保存
都会导致数据库中出现多个
delete
insert
语句


有哪种解决方案可以在不牺牲太多域和数据模型的情况下解决此问题?

这是一个完美的应用案例

我创建了这个库,以便在JPA模型和自定义接口或抽象类定义的模型之间进行简单的映射,类似于类固醇上的Spring数据投影。其思想是以您喜欢的方式定义目标结构(域模型),并通过JPQL表达式将属性(getter)映射到实体模型

实体视图也可以是可更新和/或可创建的,即支持刷新更改,这可以用作DDD设计的基础。 可更新实体视图实现脏状态跟踪。您可以内省实际更改或刷新更改的值

您可以将可更新的实体视图定义为抽象类,以隐藏“实现细节”,例如,保护修饰符后面的主键,如下所示:

@UpdatableEntityView
@EntityView(ProductJpaEntity.class)
public abstract class Product extends Aggregate {
    @IdMapping
    protected abstract ProductId getProductId();
    public abstract Set<ProductBacklogItem> getBacklogItems();
}
@UpdatableEntityView
@EntityView(ProductBacklogItemJpaEntity.class)
public abstract class ProductBacklogItem extends DomainEntity {
    @IdMapping
    protected abstract BacklogItemId getBacklogItemId();
    protected abstract ProductId getProductId();
    public abstract int getOrdering();
}
@updateableEntityView
@EntityView(ProductJpaEntity.class)
公共抽象类产品扩展了聚合{
@IdMapping
受保护的抽象ProductId getProductId();
公共抽象集getBacklogItems();
}
@UpdateEntityView
@EntityView(ProductBacklogItemJpaEntity.class)
公共抽象类ProductBacklogItem扩展了DomainEntity{
@IdMapping
受保护的抽象BacklogItemId getBacklogItemId();
受保护的抽象ProductId getProductId();
公共抽象int getOrdering();
}
查询是将实体视图应用于查询的问题,最简单的就是按id进行查询

Product p=entityViewManager.find(entityManager,Product.class,id)

保存,即刷新更改也很容易

entityViewManager.save(entityManager,产品)


Spring数据集成允许您像使用Spring数据投影一样使用它:对于刷新更改,您可以在存储库中定义一个
save
方法,该方法接受可更新的实体视图

库看起来很有趣,但在上面的示例中我看到了问题,通过注释,视图类仍然依赖于Jpa类。问题方法(以及洋葱架构背后)的想法是避免这种依赖性。您希望如何避免这种依赖性?在某个时刻,你必须以某种方式连接模型。由于此依赖项仅在注释级别上,因此您可以使用
运行时
依赖项范围,因此域模型的使用者不需要依赖于您的持久性模型。您的
产品BackLogitemJPaeEntity
应该是一个拥有自己的
@PrimaryKey
@实体,然后,当您收到
产品
时,只需将
ProductBacklogItem
列表转换为
ProductBacklogItemJpaEntity
列表,将其设置为
ProductJpaEntity
并保存即可。如果
产品
域对象中的列表包含所有待办事项,则在您可以
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...?
    }
}
@UpdatableEntityView
@EntityView(ProductJpaEntity.class)
public abstract class Product extends Aggregate {
    @IdMapping
    protected abstract ProductId getProductId();
    public abstract Set<ProductBacklogItem> getBacklogItems();
}
@UpdatableEntityView
@EntityView(ProductBacklogItemJpaEntity.class)
public abstract class ProductBacklogItem extends DomainEntity {
    @IdMapping
    protected abstract BacklogItemId getBacklogItemId();
    protected abstract ProductId getProductId();
    public abstract int getOrdering();
}