Orm 具有干净持久层(DAO、工厂等)的域类/实体

Orm 具有干净持久层(DAO、工厂等)的域类/实体,orm,associations,entity,dao,abap,Orm,Associations,Entity,Dao,Abap,在没有ORM框架支持的情况下,将域对象/实体与持久性层结合起来的干净方法是什么 我有域类/实体zcl\u文档和zcl\u文档请求(1:n)。我希望域类只包含核心域逻辑,没有基础设施,没有“助手”,没有持久性/加载机制 在ABAP中,我为每个公开为公共只读数据属性的实体定义了“clean”结构(毕竟我们在ABAP中)。这样,我就不需要在实体上使用一堆getter,并最小化核心域逻辑的方法 为了获得一个薄的持久层,我为每个数据库表(包括可选的文本表和内容)定义了DAO-接口,这些接口可以读取、保存和

在没有ORM框架支持的情况下,将域对象/实体与持久性层结合起来的干净方法是什么

我有域类/实体
zcl\u文档
zcl\u文档请求
(1:n)。我希望域类只包含核心域逻辑,没有基础设施,没有“助手”,没有持久性/加载机制

在ABAP中,我为每个公开为公共只读数据属性的实体定义了“clean”
结构(毕竟我们在ABAP中)。这样,我就不需要在实体上使用一堆getter,并最小化核心域逻辑的方法

为了获得一个薄的持久层,我为每个数据库表(包括可选的文本表和内容)定义了
DAO
-接口,这些接口可以
读取
保存
查找。它们的返回类型始终是
结构
或结构表,而不是实体对象本身。因此,我有一个可测试/可替换的瘦持久层。这个持久性层现在也可用于进行海量数据处理的报告中,因为我不必创建对象实例或对象图,我可以使用(希望是干净的)结构

要实例化一个实体,通常每个实体都有一个公共静态的
create
(工厂)方法,该方法采用“clean”结构,验证并生成其实例。与其他对象有基本关联的实体更难创建,因为还必须创建从属对象。这些实体拥有自己的
zcl\u文件\u请求\u管理器
(注明名称)。经理知道如何
创建
(工厂)和
保存
实体,包括所有关联对象。因此,它也是实体的朋友

工厂是唯一知道DAO的地方,以保持实体本身不受基础设施/持久性的影响。加载是迫不及待地完成的,我不知道如何在实体中创建透明的延迟加载,而不需要太多的基础设施管理代码

使用它将如下所示:

create object lo_docreq_mng exporting dao, dao, dao, dao,...

lt_docreq = docreq_dao->find_by_x( ... ) // table of structure

foreach lt_docreq as ls_docreq // structure
  lo_docreq = lo_docreq_mng=>create( ls_docreq ) // factory => instance

  lo_doc = lo_docreq->get_document( ) // was created with document-instance

  lo_docreq->do_something_mutating( ).      
  lo_docreq_mng->save( lo_docreq) // save including dependent objects
这是可行的还是有气味?
欢迎发表任何评论。

我喜欢你的方法。我会改变一些事情:

1) 为了让域对象的用户不受构造代码的影响,您可以提供一个docreq类,该类返回实体列表而不是结构:

lt_doc = doc_qry->find_by_x( ... ) // table of entities
foreach lt_doc as lo_doc 
  lo_doc->do_something_mutating( ).      
  lo_doc_mng->save( lo_doc ) // save including dependent objects
这种用法不太容易出错,并澄清了代码中的业务逻辑。由于希望经常使用您的实体,您可以简化其他开发人员的使用

2) 也许你也可以去掉save方法。为什么必须显式调用save?根据我的经验,保存或放弃某个内容的决定是由正在运行的事务(顶级报告或正在运行的UI)的控制器做出的。但不应将其置于某种业务或服务方法/功能中

3) 我不会选择静态方法。首先,它们很容易实现,但对于以后的更改,它们可能会变成地狱


关于使用ORM的讨论:我不会混淆持久性和域逻辑,因为它降低了可测试性。单独使用ABAP-ORM作为持久层没有什么好处。为什么要将数据包装在类中,并像使用简单的abap结构一样使用它(在大多数情况下)?另一方面,它缺少一个好的DQL。

我知道这是一个老问题,但在我最近的项目中,我一直在尝试为同样的问题找到一个好的解决方案

我大体上同意您的方法,并遵循与您非常相似的方法,只是我没有定义任何DAO类型的对象。大多数时候,我不仅定义了一个管理器类,还定义了两个独立的类:用于管理数据库检索/保存的存储库和用于创建新的有效实例的工厂。这只是为了不违反SRP(同样,我倾向于将它们定义为接口)。这也与编写单元测试配合得很好


正如您已经提到的,最大的问题是急切地加载关系,一旦开始处理大量数据,这种关系就会很快崩溃。解决方案可能是存储库应该知道每个实体的唯一标识符(即数据库中的主键),并且只在实例化时获取这些标识符,但我实际上还没有实现。

在ABAP中不使用现有ORM的原因是什么,据我所知,您的请求,已经涵盖了您需要的大部分内容?我认为持久化类很难看,它会生成大量的get/set。我不想让类与持久性紧密结合。相反,如果可能的话,我希望得到一个带有薄持久层的干净的域类…“我认为持久类很难看”-我不这么认为,除非你有一些严重的顾虑:-)好的,这是一个不同的争论。尽管如此,我最初的问题仍然存在:如何使用现有的机制和工具,将实体与DAO和级联加载/保存干净地结合起来。根据我的经验,重新设计车轮并不能使汽车运行更平稳。今天,我将放弃ABAP中作为普通对象的建模,而是使用BOPF的服务层方法。尽管它的API/接口非常通用,技术性很强,而且有点难看,但与自己构建持久性和对抗事务、性能缓冲、急/缓加载和大规模操作相比,它有着巨大的优势。谢谢你的回答。BOPF目前不是我熟悉的东西,但从它的声音来看,它值得研究。