论坛首页 Java企业应用论坛

有了hibernate是否还需要Dao?

浏览 28643 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-12-25  
抛出异常的爱 写道
zbird 写道
就个人而言,我不喜欢DAO。
DAO不是万能药,解耦并不是加个DAO就能解决的问题。
对于大多的简单操作,Hibernate封得已经够完善了,大多时候加个DAO费力不讨好。
如果操作复杂,Service层过于混乱,这时候再抽取出个DAO也没什么不可以。
说到使用DAO解耦,大家最喜欢举的例子就是换实现。以前是说换数据库,现在Hiberate对数据库封得差不多了。于是说法改成将hibernate换成其他的实现,如jdbc等。
但真实项目中有谁有事没事的去换这些东西。
耦是有了才需要解的,如果凭空想出很多不实在的需求,无非是给自己自找麻烦。
我一直在说....
不是为了移植
而是为了管理方便

当然你可以把业务逻辑
与数据库逻辑写在一起
当只有一二个表时
并没什么不好解理
当一个操作关系到:
日志表,
权限表,
业务级联表,
操作记录表,

用人类的智力要从这么多的代码中找到逻辑.....还是差点意思

根据实际情况开看嘛,如果系统复杂那用DAO也没什么不可以。
但我确实见到过不少应用就是一个简单的管理界面,就一个CRUD也非得分这么多层,而且还分得乐此不彼的。
我就不知道这些基础的CRUD能有多少复杂的逻辑。
偶尔真出现那么一两个操作复杂的,这时候你再抽一次又有什么麻烦。
0 请登录后投票
   发表时间:2007-12-25  
JAVAEYE抽风,发了两次。
删除。
0 请登录后投票
   发表时间:2007-12-25  
有的抽有的不抽
想找的时候....
你就慢慢跟吧.
PS:
引用

日志表,
权限表,
业务级联表,
操作记录表,

这几个操作可能是所有的crud都要有的.
0 请登录后投票
   发表时间:2007-12-25  
这么多表相关的操作,为什么不用过程处理?为了方便数据库移植?
0 请登录后投票
   发表时间:2007-12-26  
flash 写道
这么多表相关的操作,为什么不用过程处理?为了方便数据库移植?
后加的需求.
0 请登录后投票
   发表时间:2007-12-26  
moonranger 写道
我觉得设计DAO的重要原因是为了将持久化的实现与持久化接口分开。万一哪天你不用Hibernate了,DAO的接口还可以重用。而如果你直接使用Hibernate的话,你的业务逻辑层代码就和Hibernate耦合了。
这只是我肤浅的理解而已,呵呵~
0 请登录后投票
   发表时间:2007-12-26  
考虑那么多做什么?

多分几层的,等你几个月后再回来维护系统就会觉得“挺好的”。

少分几层的,当老板只给你一天时间的时候也很爽嘛。

不想用过程(或者像我这样不会写过程)的,就会认为在Java代码里写业务逻辑是天经地义的,我很不喜欢把业务处理写到数据库的过程里面去,因为我不会写,也因为我喜欢数据库无关,哈哈。
0 请登录后投票
   发表时间:2008-01-03  
我也是初学hibernate,顺便买了一本<深入浅出Hibernate>,书里就说了
1.一级缓存的出现可以抵消使用hibernate所带来额外的性能开销.    p222
2.在Hibernate的项目中使用DAO唯一的站得住脚理由就是抽象hibernate.    p343

但是如果使用了DAO+service,每次的service里的操作完成后就会调用session.close().这样就无法利用一级缓存了.这样是不是会非常影响性能呢?
0 请登录后投票
   发表时间:2008-01-04  

依次回答你的疑问:
1.  DAO应该是细颗粒度的对持久数据的CRUD, Hibernate的API是最细颗粒度数据访问, 例如现在有这样一个需求
:根据表现层传过来的一个订单号,查出这个订单下面的所有商品.你可能第一步会先得到某个订单;第二步根据配
置好的一对多关联关系得到相关的商品集合.可以看到第一步属于数据访问逻辑,第二步依然是,并且两者在逻辑
语义上属于一个数据访问逻辑(根据OrderId得到Order下的OrderItem List).我想你大概不想将这两步拆开来揉合
到业务逻辑中去吧!所以DAO模式的主要作用就是封装对数据的访问和持久化,将数据访问和持久化逻辑从业务逻辑
中解藕出来,从而实现了代码复用,也便于维护.
    看到有人仍在用One Session Per Operation这种反模式,似乎又看到了当年的自己.你说的没有错,每次Session
关闭后,Session级别的缓存确实失效了,如果你对于Session级别的缓存比较在意,不妨试试OPenSessionInView.但是
这种模式也有一些问题,对于Hibernate Session和Transaction的管理众说纷纭,不知道目前有没有一个最优解决方案.

 

2.  关于你对Action的描述和对Service层的疑问,我想说Action在本质上应该属于MVC中的C,在复杂的企业运算里,它
最多可以算作一个控制器,控制业务的流程,而不应该将业务逻辑放入其中.为什么?对于将业务逻辑一概放入Action里,
我将之称为"业务逻辑前移",就是说业务逻辑层变"瘦"了,甚至没有了.这样,你的业务逻辑就跟具体的表现层框架
强耦合在一起,无法达到业务逻辑的重用.如果下个项目(相同或相似的业务领域或行业)你们不用Struts,改用Webwork
或者Tapstry作为展现层框架,你不得不重写业务逻辑.
    关于你对位什么要有Service层的疑问.在受到Martin Fowler批评的Anemic Model中Service层主要的作用不外乎
划分事务的边界,对Web层提供一个统一的Facade以供调用.在Rich Model 中除了上述的两个作用外,Service还和
DomainObject协同封装业务逻辑.

 

3.  在你的第3点中提到的分层方法,我称之为"业务逻辑后移",当年我也写过.关于你的描述准确点讲应该是这样:
Controller(Struts的Action)+ 贫血的DomainObject(哑数据容器)+DAO(封装了业务逻辑并在其前后包上Hibernate的
Transaction).这样就将业务逻辑后移,移到了数据访问对象DAO中,这样业务逻辑就和具体的持久层框架强耦合在一起,
无法重用,同时这种设计也违反了SRP(Single Responsibility Principle).
    PS:如果我没记错的话,Apache的一个开源项目Roller好像就是用的这种架构.

0 请登录后投票
   发表时间:2008-01-05  
有这么个业务:
页面传来一个user_id,通过这个userId查找这个用户父亲的user_id(字段为f_id),然后获得父亲的所有图书.
我项目中的做法:
dao中方法,
//1.通过userId获得fId 
public String getFIdFromUserId(String userId);
//2.通过FId获得书籍
public List getBooksFromFId(String fId);

service中的方法
//1.通过userId获得fId 
public String getFIdFromUserId(String userId);
//2.通过FId获得书籍
public List getBooksFromFId(String fId);
//3.获得指定userId父亲的书籍
public List getBooks(String userId){
    调用方法1;
    调用方法2;
}


疑问: 大家写这种需求的代码的时候,是否也这样写?
当中的"获得指定userId父亲的书籍"方法,是否需要单独在dao中封装一个方法,使之减少对数据库的访问,访问一次就可以.
另外,dao和service层,很是令人郁闷,每次有新需求的时候,都要在dao中加个方法,然后再在service中加个调用dao中的方法,感觉是多此一举.
我曾经问过朋友能不能把dao或者service层去掉一个,朋友说和什么事务有关系,不能去掉

大家有什么看法?
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics