Architecture 为什么要将DAO层置于持久层之上(如JDO或Hibernate)
数据访问对象(DAO)是一种常见的设计模式,由Sun推荐。但最早的Java DAO示例直接与关系数据库交互——本质上,它们是在进行对象关系映射(ORM)。现在,我看到DAO位于成熟的ORM框架之上,比如JDO和Hibernate,我想知道这是否真的是个好主意 我正在开发一个使用JDO作为持久层的web服务,并且正在考虑是否引入DAO。在处理包含其他对象映射的特定类时,我预见到一个问题:Architecture 为什么要将DAO层置于持久层之上(如JDO或Hibernate),architecture,persistence,data-access-layer,jdo,dao,Architecture,Persistence,Data Access Layer,Jdo,Dao,数据访问对象(DAO)是一种常见的设计模式,由Sun推荐。但最早的Java DAO示例直接与关系数据库交互——本质上,它们是在进行对象关系映射(ORM)。现在,我看到DAO位于成熟的ORM框架之上,比如JDO和Hibernate,我想知道这是否真的是个好主意 我正在开发一个使用JDO作为持久层的web服务,并且正在考虑是否引入DAO。在处理包含其他对象映射的特定类时,我预见到一个问题: public class Book { // Book description in various
public class Book {
// Book description in various languages, indexed by ISO language codes
private Map<String,BookDescription> descriptions;
}
公共课堂教材{
//各种语言的书籍描述,按ISO语言代码编制索引
私有地图描述;
}
JDO足够聪明,可以将其映射到“BOOKS”和“bookscriptions”表之间的外键约束。它透明地加载BookDescription对象(我相信使用延迟加载),并在持久化Book对象时持久化它们
如果我要引入一个“数据访问层”,编写一个像BookDao这样的类,并将所有JDO代码封装在其中,那么JDO对子对象的透明加载不会绕过数据访问层吗?为了保持一致性,是否应该通过某个BookDescriptionDao对象(或BookDao.loadDescription方法)加载并持久化所有BookDescription对象?然而,以这种方式进行重构会使操作模型变得不必要的复杂
所以我的问题是,直接在业务层调用JDO(或Hibernate,或任何您喜欢的ORM)有什么错?它的语法已经相当简洁,并且与数据存储无关。将其封装在数据访问对象中有什么好处(如果有的话)?这取决于层的目标是什么。您在中添加了一个抽象,以提供一组不同于另一组的语义。一般来说,有更多的层次来简化一些事情,例如未来维护的开发。但它们还有其他用途
例如,ORM代码上的DAO(或持久性处理)层提供了专门的恢复和错误处理功能,您不想污染业务逻辑。您提出了一些观点。但我仍然使用Dao层,原因如下:
在同一层中具有常规和特定的需求允许重用(例如,拦截可以确保在需要时打开/提交数据库连接)
当使用像JDO或JPA这样的ORM工具时,DAO是一种反模式。在这种情况下,创建一个“数据访问层”是完全没有必要的,它只会给代码库增加额外的代码和复杂性,使其更难开发和维护 根据我以前的经验,我建议使用一个简单的静态facade,比如说
持久性
,为持久性相关的操作提供一个易于使用的高级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);
...
列出最便宜的书籍=
查找(“从b.price<?”的图书中选择b”,lowPriceForBooks);
...
书b=新书(…);
(b);
...
Book existingBook=加载(Book.class,bookId);
删除(现有的书籍);
...
上面的代码尽可能简单,并且可以很容易地进行单元测试。实际上,它必须比所有这些答案都要简单。这些模式都是关于层的。您不希望循环引用,因为您制作的层只能知道它们上面的内容。您希望您的UICode能够引用任何和所有服务,您的服务代码能够引用任何和所有DAO
通常,我总是将我的数据访问操作包装在DAO中,并敲打它周围的接口。我相信大多数DAO是由人们出于历史(历史;])原因添加的。您是对的,它们最初的意思是作为在ORM之前执行CRUD操作所需的SQL胶水的方便封装。如今,有了透明的持久性,它们的角色现在基本上是多余的 什么是不
@Transactional
public void doUnitOfWork() {
// some persistence operation here
// some other persistence operation here
}
//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