Java 如何在DDD中实现持续无知?

Java 如何在DDD中实现持续无知?,java,scala,domain-driven-design,persistence,Java,Scala,Domain Driven Design,Persistence,我正在处理一个项目的持久化层,该项目涉及工作区,每个工作区可能包含零个、一个或多个文档。(我正试图跟进,但我的问题可能与此没有直接关系。) 问题1:我应该把持久性分开吗?也就是说,您设计实体和值类的方式是否可以 在内存中创建实体和值,就像在没有持久性的情况下一样(可能使用工厂方法workspace.newWorkspace(…)),以及 调用一个单独的persist()方法(可能在存储库中)来处理持久性 或者我的工厂方法workspace.newWorkspace()是否应该创建一个持久化实

我正在处理一个项目的持久化层,该项目涉及
工作区
,每个工作区可能包含零个、一个或多个
文档
。(我正试图跟进,但我的问题可能与此没有直接关系。)

问题1:我应该把持久性分开吗?也就是说,您设计实体和值类的方式是否可以

  • 在内存中创建实体和值,就像在没有持久性的情况下一样(可能使用工厂方法
    workspace.newWorkspace(…)
    ),以及
  • 调用一个单独的
    persist()
    方法(可能在存储库中)来处理持久性
或者我的工厂方法
workspace.newWorkspace()
是否应该创建一个持久化实体(事务关闭后将持久化)

如果这个问题的答案是“分离,老兄!”那么我想知道如何以优雅的方式实现这一点。我的第一种方法是(用伪代码):

类工作区(标题:字符串,文档:列表[文档],id:选项[长]){ def添加(d:文档)=/。。。 def删除(d:文档)=/。。。 } 但是,如果一个工作区可以有许多文档,这是不好的(受RAM限制)。我的下一个方法是:

类工作区(标题:String,docSupplier:docSupplier,id:Option[Long]){
def add(d:文档)=docSupplier.add(d)
def删除(d:文档)=文档供应商。删除(d)
}
这样,工作区工厂就可以创建新的工作区,如下所示:

类工作空间{
def newWorkspace(title:String)=新工作区(title,
//保存简单“清单[文件]的供应商`
新供应商(){
定义添加(d:文档)=列表。添加(d)
def删除(d:文档)=列表。删除(d)
},id)
}
此外,我的存储库可以重建工作空间它从数据库中获取的内容如下:

类工作空间存储库{
def findById(id:Long)=/…调用`createDoc()`
def createDoc(…)=新工作区(标题,
//能够记住更改的供应商,以便将更改持久化到“persist”()`
新供应商(){
def add(d:文档)=更改。记住d(d)
def删除(d:文档)=更改。记住删除(d)
},id)
}
问题2:这就是解决问题的方法吗?!Puh,有很多代码,有很多样板

我应该把持久性分开吗

是的,就像你描述的那样

或者我的工厂方法Workspaces.newWorkspace()应该创建一个 持久化实体(事务完成后将持久化) 关闭)

否,因为持久化临时实体应该是一个显式操作,例如在添加新工作区时。工厂处理对象实例的创建,存储库处理持久性。如pabrantes所示,工作单元模式可以与存储库结合使用

但是,如果一个工作区可以有许多文档,这是不好的 (受RAM限制)

<>这是DDD中的一个常见情况——在达到持久性无知时,你必须考虑技术约束。首先要考虑的是<代码>工作空间< /C>实体是否需要引用<代码>文档实例的集合。是否有
工作区
需要强制执行的不变量?是否存在事务边界?对象引用仅限于。另一种方法是使用存储库。因此,在
工作区
类上没有
文档
集合,而是提供了一个存储库方法,允许检索与特定工作区关联的文档。考虑到文档的数量可能很大,存储库还可以支持分页和筛选


还可以深入探讨这些问题。

看一看名为工作单元的设计模式:@pabrantes,感谢链接,这确实很有意义。您知道Java/Scala中有哪些实现可以在这里重用吗?我知道一个实现,但它位于Java的STM(软件事务内存)中。虽然如果您仍然想检查实际代码,这里是工作单元类的直接链接(在本例中称为DBChanges)。作为旁注,如果你想使用DDD,你可能想看看这个项目,它是纯DDD,并且100%隐藏了持久性。作为旁注,我也看到了DDD方法与你在问题中介绍的存储库设计,但所有的锅炉板都是生成的(因为它总是相同的)。如果你愿意,我可以收集我们所说的一切,然后写一个答案。你重建工作区的方式看起来很适合,因为有一个很酷的Scala/Akka/DDD项目使用了你可能感兴趣的模型:@eulurfx,非常感谢你的评论和有趣的链接。在我的实际实现中,
DocSupplier
实际上提供了分页功能,但是在很多代码中,存储库可能会更简单(尽管更贫乏!)。嗯,说到事务,我对上面的
workspaceprepository
有一个问题:这里使用的
DocSupplier
能否利用ACID的隔离特性?例如,我可以将文档保存到数据库中(在当前事务中),而不是
changes.rememberAdd(d)
。最大的好处是查询将返回它。缺点:即使不调用
persist()
,它实际上也会被保存(除非回滚)。我想知道是什么反对这一点?在事务中保存文档没有问题,但我认为根本不需要
DocSupplier
Workspace
类可以有一个用于创建文档实例的工厂方法,然后由周围的appl显式保存