数据访问对象(DAO)是一种常见的设计图案,并通过太阳推荐 但Java的DAO的最早的例子直接与关系数据库交互 - 他们在本质上,这样做的对象关系映射(ORM)。 现在,我看像JDO和Hibernate成熟的ORM框架之上的DAO,我不知道这是否真的是一个好主意。
我正在开发使用JDO作为持久层的web服务,并正在考虑是否要引进的DAO。 与包含地图等对象的特定类打交道时,我可以预见到的问题:
public class Book {
// Book description in various languages, indexed by ISO language codes
private Map<String,BookDescription> descriptions;
}
JDO是足够聪明的这个“书”和“BOOKDESCRIPTIONS”表之间的映射到外键约束。 它透明加载BookDescription对象(使用延迟加载,我相信),并且将它们保存在Book对象持久化。
如果我是引入“数据访问层”,写像BookDao一类,并在此封装所有的JDO的代码,那么就不会这样JDO的孩子的透明负载对象被绕过数据访问层? 为了保持一致性,应该不是所有的对象BookDescription被加载,并通过一些BookDescriptionDao对象(或BookDao.loadDescription方法)持续? 然而,在这种方式重构将使操纵模型必要的复杂。
所以我的问题是,什么是错调用JDO(或休眠状态,或任何ORM你喜欢)直接在业务层? 它的语法已经相当简洁,它是数据存储无关。 什么是优势,如果有的话,在数据访问对象封装呢?
Answer 1:
这取决于你的层的目标是什么。 你把一个抽象了另一组以提供一组不同的语义。 一般来说进一步层有简化出头如未来maintennance的发展。 但是,他们可以有其他用途。
例如一个DAO(或持久性处理)层上的ORM密码供应专业恢复和错误处理功能,你不想污染的业务逻辑。
Answer 2:
你让一些要点。 但我仍然使用了DAO层,这里的原因:
数据库访问是到远程系统调用 。 在所有这些情况下(也Web服务,AJAX等),互动的粒度必须足够大。 许多微小的通话将杀死性能。 这种性能的必要性需要系统的往往不同的观点,或层(这里,道层)。
有时候,你的持久操作只加载/保存/删除的对象。 一个独特道(或超;考虑仿制药)可以负责这一点,所以你不必一次又一次地编写这些方法。
但往往,你也有特定的需求,如跑步是不会自动ORM创建的具体要求 。 在那里,你的代码与特定的道法的具体需求(重用往往是可能的)。
具有在同一层常规和特殊的需要允许重用(例如,拦截可以确保在需要时数据库连接是打开/ COMMITED)。
Answer 3:
DAO已经失去了一段时间的意义。
在J2EE天,当它成为一个流行的模式,一个DAO是一个类,你可以同时满足多个数据源 - 由一个供应商数据库,由另一个数据库,文件 - 并提供一个单一的地方包裹查询通信数据。
有大量的范围进行再利用,因此对于特定实体的DAO对象很可能延长其容纳在可重复使用的东西,这本身实现的DAO接口的抽象DAO。
后J2EE / EJB中,DataMapper的和DataSource模式(或简单的系统,ActiveRecord的)走红执行相同的作用。 然而,DAO成为参与任何持久化对象流行语。
Nowdays,术语“DAO”已经黯然成为“一类的使我与我的数据库进行通信”的代名词。
随着ORM / JPA,多一个真正的,J2EE时代DAO的理由提供开箱即用。
在后面的数据源模式的情况下,JPA的EntityManager的是类似于数据源,但通常经由PersistenceUnit XML定义中提供并经由IoC的实例化。
现在可以恰好一次使用存储库的图案来提供曾经住在DAO或映射器CRUD方法。 有没有必要AbstractDao的公司 - 的ORM产品是足够聪明的接受对象(),并知道它是坚持它。
Answer 4:
当使用像JDO或JPA ORM工具,DAO的是一个反模式。 在这种情况下,建立一个“数据访问层”是完全没有必要,只会增加额外的代码和复杂的代码库,使其难以开发和维护。
根据我以前的经验,我会建议使用一个简单的静态的门面,说Persistence
,提供一个易于使用,持久性相关的操作的高级API。
然后,您可以使用静态导入,就能轻松使用这些方法的任何地方,他们是有用的。 例如,你可以像下面的代码:
List<Book> cheapBooks =
find("select b from Book where b.price < ?", lowPriceForBooks);
...
Book b = new Book(...);
persist(b);
...
Book existingBook = load(Book.class, bookId);
remove(existingBook);
...
上面的代码是作为容易和简单越好,并且可以很容易地进行单元测试。
Answer 5:
一个字:交易
就拿情况下,我必须在一个事务中执行两个数据更新操作。 这些操作共同构成一个逻辑工作单元。 我的商业逻辑所要表达自己的工作单元而言,它并不希望与事务边界打扰自己。
所以我写了一个DAO。 使用Spring事务和Hibernate把这个伪代码:
编辑删除HQL这是得罪@Roger这么多,但是这是不相关的点
@Transactional
public void doUnitOfWork() {
// some persistence operation here
// some other persistence operation here
}
我的商业逻辑调用doUnitOfWork(),它开始一个事务,执行两种持久化操作,然后提交。 它不知道也不关心有关交易,或进行什么样的操作。
此外,如果DAO实现与doUnitOfWork()方法的接口,则业务逻辑可以编码到接口,从而更容易进行单元测试。
一般来说,我一直包在我的DAO数据访问操作,并捶围绕它的接口。
Answer 6:
我相信大多数的DAO是由人来添加histerical(历史])的原因。 你是正确的,他们intially意味着作为在预ORM天执行CRUD操作所需的SQL胶水方便封装。 如今,随着透明的持久性,它们的作用是现在基本上是多余的。
什么是合适的,现在是库和服务的概念:
存储库:存储在特定ORM代码实现的查询方法的集合的类(例如,休眠或JDO)
通常,你可以创建一个抽象基类库,然后为你提供实现代码的所有查询方法是特定于您的ORM成一个ORM的具体实施。 这种方法的好处是,你可以创建一个MockRepository实行,以帮助测试您的应用程序,而无需使用DB。
服务:存储的可编排非平凡改变/添加到对象模型方法的集合的类(通常ORM无关的代码)。
这有助于保持你的应用程序主要是ORM独立 - 端口应用到另一个ORM实际上只涉及到一个新的ORM特定仓储类(ES)的实施。
Answer 7:
我想,该图案“每个实体DAO类”是一个ORM管理数据层绝对是多余的。 相反,DAO层应当由一组中的一个通用型,关于任意的实体类操作CRUD方法集和大量的该对数据执行更复杂的操作方法。 如果这项功能是足够大,那么DAO层应分为基于域标准的多个类,是什么使这种方法更类似于面向服务的体系结构。
Answer 8:
这一切的介绍层的目的是使维护简单方便。
- 数据访问层
- 业务层
- 表示层
在第一层(数据访问层)的目的是处理与数据库的逻辑和防止业务层从知道任何细节DB。
数据访问层使用POJO或EJB(DAO)来实现的IoC和POJOEJBs使用Hibernate或者ORM映射到实际与数据库层处理。
所以,如果你希望你的业务逻辑不应该关心它,你想DAO照顾这个东西和如何数据库正在被使用,访问和更新,
DAO可以支持改变不同的表通过使数休眠的呼叫,以支持操作的逻辑。
从本质上讲,你是在两层又名DAO和Hibernate再次打破其功能实现在数据访问层分层的方法。
Answer 9:
如果您使用的ORM: 享受透明持久性的支持 ! 不要使用DAO的包裹ORM的API。 由于这是很好这里说,DAO的是奥姆斯之前。 奥姆斯已经介绍的概念从面向对象数据库,就像可达透明的持久性和持久性。 你要利用这一点,因为它会让你的生活更轻松,你的代码美丽。 假设你正在建模部门和员工......一个用例可能是创建一个新的部门,建立一个新员工,增加员工到部门......你会做什么?
//start persistence context
...
Department dept1 = new Department("department1");
dept1.addEmployee(new Employee("José", 10503f));
em.persist(dept1);
...
//close persistence context
部门,员工和他们的关系现在是永久性的。
现在假设你有一个现有的员工加入和现有的系...你会做什么? 很简单:
//start persistence context
...
Department aDepart = hibernateSession.load(Department.class, dId);
Employee anEmployee = hibernateSession.load(Employee.class, eId);
aDepart.addEmployee(anEmployee);
...
//close persistence context
很简单归功于透明的持久性和持久性的可达性,Hibernate对(像其他的ORM)实现。 没有的DAO的。
只需编写你的域模型,并认为你是在内存持续。 凭借良好的映射策略,ORM会坚持透明做什么你在内存中。
这里更多的例子: http://www.copypasteisforword.com/notes/hibernate-transparent-persistence http://www.copypasteisforword.com/notes/hibernate-transparent-persistence-ii
Answer 10:
它实际上必须比所有这些答案简单做出来是。 这些模式都是关于层。 你不想循环引用,你应当层,可以只了解事情在他们之上。 您希望您的UICODE能够引用任何和所有的服务,您的服务代码能够引用任何和所有的DAO。
- DAO
- Service
- UICode
与POJO的自上而下传递给底部。
文章来源: Why put a DAO layer over a persistence layer (like JDO or Hibernate)