Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.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
领域驱动设计-领域模型与Hibernate实体_Hibernate_Entity_Domain Driven Design - Fatal编程技术网

领域驱动设计-领域模型与Hibernate实体

领域驱动设计-领域模型与Hibernate实体,hibernate,entity,domain-driven-design,Hibernate,Entity,Domain Driven Design,Hibernate实体是否与域模型相同 请参见下面的示例 方法1-域模型和实体是同一类。域模型“是一个”实体 方法2-域和实体是不同的功能。域模型“具有”实体 从以上两种方法中,哪一种是实现DDD的正确方法?我认为方法2是正确的方法,因为您实际上是在控制对敏感对象的访问,并且封闭对象(域模型)拥有域模型上的所有业务逻辑/操作。但我的同事们认为,它们基本上是一样的。根据它们,Hibernate实体的目的是表示给定系统中的域模型。将实体建模为域模型实际上使设计更简单。这是因为存储库需要一个实体来执行

Hibernate实体是否与域模型相同

请参见下面的示例

方法1-域模型和实体是同一类。域模型“是一个”实体

方法2-域和实体是不同的功能。域模型“具有”实体


从以上两种方法中,哪一种是实现DDD的正确方法?我认为方法2是正确的方法,因为您实际上是在控制对敏感对象的访问,并且封闭对象(域模型)拥有域模型上的所有业务逻辑/操作。但我的同事们认为,它们基本上是一样的。根据它们,Hibernate实体的目的是表示给定系统中的域模型。将实体建模为域模型实际上使设计更简单。这是因为存储库需要一个实体来执行CRUD操作。因此,如果模型“有”实体,则必须将存储库的依赖项注入域模型中以保存实体。这将使设计变得不必要的复杂。

因为您在本例中提到了Hibernate技术,这意味着您正在谈论一个实现。领域驱动设计是关于抽象的,例如模型,以及它的实现

模型可以以不同的方式实现。在您的示例中,您展示了两种不同的实现,它们表示相同的模型

这是关于你所面临的问题

您询问域模型是否与休眠实体相同。答案是否定的

Hibernate实体是一种特定于技术的东西,在本例中,它是ORM框架的一部分Hibernate实体DDD实体由DDD定义是不同的事情,因为DDD实体是一个抽象的东西,如果定义了一个想法(模式),并给出了这个想法是什么以及它代表什么的指导方针Hibernate实体是一个实例化、跟踪、持久化和丢弃的Java对象 垃圾收集

人们只是对不同的事物使用相同的术语,这可能会导致混淆(不能怪他们,命名事物是软件中两个难题之一)

您可以使用Hibernaty Entities或任何其他特定于技术的类型,如Entity Framework Entity(即OO程序中的对象)来实现域模型。相同的域模型可以使用不同的技术在不同的语言中实现。这些实现将根据技术提供的内容而有所不同

例如,如果您正在使用MongoDB编写NodeJs后端,并且希望使用ORM实现域模型,那么您将不得不使用(可能是Mongoose),因为人们只实现了这些(至少我找不到任何其他非活动记录的框架,如果你找到了,请告诉我)

在文章中,Eric Evans谈到了技术如何帮助你实现一个模型,或者如何一路与你抗争。当它与你抗争或者没有提供好的机制时,你只需要知道如何解决这个问题

有时,ORM有一些要求,您不想将这些内容公开给其他代码,因此您可以在方法2中使用类似的包装器。其中一些包括诸如public get set方法、public构造函数等。它们中的大多数都使用反射,并且可以具有私有内容,但仍然存在许多问题,例如具有私有属性ate构造函数没有参数来满足框架的要求,而您的代码中有很多与您的模型无关的东西,但它们是因为您的框架需要它们而存在的(糟糕!)。这也可能导致错误。使用默认构造函数比使用带参数或静态工厂方法的好构造函数更容易出错。此包装器可以表示更纯粹的域模型,而不必使用框架所携带的必要的邪恶,以便您可以使用它们

在一个项目中,这变得如此丑陋,以至于我们决定在存储库中使用原始SQL,这样我们就不必处理框架中的所有内容。实现很好,很纯粹,我们做得更快。有些人认为框架加快了速度,大多数情况下都是这样,但当框架与您和合作者发生冲突时de有缺陷,调试不有趣,因此编写原始SQL很容易。在这种情况下,使用聚合遵循DDD的指导原则,我们的模型很好地解耦了,并且我们没有复杂的查询,这会降低开发速度

Hibernate实体是否与域模型相同

不完全是这样。实际上,它们之间的界限可能非常模糊

域驱动设计的一个主张是,您可以将持久性问题从域模型中分离出来。域模型在内存中保存某些业务的当前状态表示,以及控制该业务状态如何随时间变化的域规则

存储库充当了一种边界,在应用程序中认为域实体都存储在本地内存中某处的部分和代码中知道数据的非易失性存储的部分之间

换句话说,存储库(在某种意义上)是两个功能;一个知道如何从“聚合”和存储中获取数据,另一个知道如何从存储中读取数据并从中构建聚合

ORM是将数据从外部关系数据库获取到本地内存的一种方法

所以你的负载故事看起来
@Entity
@Table(name = "agent")
class Agent
{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @Column(name = "agent_number", unique = true, nullable = false)
    private String agentNumber;

    @Column(name = "agent_name", nullable = false)
    private String agentName;

    // Busines logic methods
}
class Agent
{
    // Hibernate entity for this domain model
    private AgentEntity agentEntity;

    // Getters and setters to set the agentEntity attributes

    // Business logic
}
Use an identifier to load data from the database into a hibernate entity
copy the data from the hibernate entity into an aggregate
return the aggregate
Copy data from the aggregate into a hibernate entity
Save the hibernate entity.
Agent AgentRepository::find(id) {
    AgentEntity e = entityManager.find(id)
    Agent a = domainFactory.create( /* args extracted from e */ )
    return a
}

void AgentRepository::store(Agent a)
    AgentEntity e = entityManager.find(id)
    copy(a, e)
}

// I think this is equivalent
void AgentRepository::store(Agent a)
    AgentEntity e = entityManager.find(id)
    entityManager.detach(e)
    copy(a, e)
    entityManager.merge(e)
}