是否还应该再单设计一个DAO

07-04-11 wlmouse
我中间层打算这么设计。架构采用Spring+Hibernate。创建中间业务层的接口A。然后建立代理类B和实际的业务处理类C。B和C继承A。B是C的代理。由表现层通过B去调用C。
业务基本上都是执行HQL语句,所以还需要再建议一个Dao层吗?还是直接在C里写。如果再建立一个Dao层的话,C里基本上和B变得一样了,就是一个空空的代理,没有任何业务逻辑在里边。

fyxruben
2007-04-12 10:05
DAO依旧是大家提倡使用的,不过你也可以尝试下富血型模型!那就没有什么DAO了!

wlmouse
2007-04-12 10:22
不过目前我的设计还是比较偏向贫血,对象内的业务逻辑相对比较少,很多都被独立成服务了。我主要说的就是这些服务的设计。采用代理模式,一个接口A,然后代理类B和实际的业务处理类C继承接口A。调用的时候通过B调用C。现在就是业务上看了看,主要就是增删改查,在C里直接写HQL就可以了,逻辑业务可以说也就是这些。我觉得既然Hibernate把数据库和业务隔离了,再来一个Dao层来隔离Hibernate是否多此一举?因为业务逻辑就是HQL,如果再添一个层,类C就变得和类B差不多了,都只是一个代理了。等于我就是加了一层代理。所以我觉得没什么必要了。

fyxruben
2007-04-12 11:19
个人觉得javaeye上面对这方面的讨论很多,而且对Hibernate的封装设计也很多!有空你可以去看看!
如果你不想被侵入,用用DAO还是不错的!
个人还没有学习Hibernate,如果学,打算学习JPA!

cscs31
2007-04-12 15:09
个人认为,你现在的结构是这样的,代理层(B)、业务层(C)、数据层等等吧,你的问题是是否要在C后加一个DAO层,我认为还是有用的。
原因:你可以这么想,现在你的业务层中是一些简单的逻辑(CRUD),其实就是直接调用hibernate的方法,那么咱们来写一段程序看看。

接口:Login(String userName,String passWord) throw YourException;

delegate:
public Login(String userName,String passWord) throw YourException
{
UserService us = ServiceFactory.getService("User");
us.Login(String userName,String passWord);
}

service:
public Login(String userName,String passWord) throw YourException
{
try{
//hibernate实现
}catch(Exception e){
YourException ye = new YourException(e);
throw ye;
}
}
如果这个时候,你的C层要更改持久层实现技术,比如使用ejb,jdbc
这个时候考虑问题的时候,其实业务逻辑并没有变,只是访问的方法变了。
可是现在的架构必须去更改service层的代码。
或者在今后的技术进步中,service层出现别的技术,那么你又要重写数据访问的代码,如果改成下面这样:
service层:
public Login(String userName,String passWord) throw YourException
{
try{
UserDAO = DAOFactory.getDAO("User");//通过配置文件
User user = UserDAO.getUserByUserName(String userName);
if(isExist(user))
{
checkpassword(user);
//添加业务逻辑
checkActive(user);
}
}catch(Exception e){
YourException ye = new YourException(e);
throw ye;
}
}


DAO:
interface: User getUserByUserName(String userName) throw DBException;
implement:
UserDAOImplHibernate
User getUserByUserName(String userName) throw DBException;

如果使用别的实现方法,可以重新添加一个UserDAOImplEjb,然后通过配置文件配置,这样服务层的代码不用更改。
如果技术进步,业务层需要重写,这时候那些访问数据的代码也不用重写了。

不知道说的对不对,希望大家讨论。

还有就是,代理层到底有什么用?是和分布式有关系吗?

fyxruben
2007-04-12 22:07
个人有种想法
JSP-->Action-->JSP
    |
   Service <--> logic / bean
     |
     DAO
前端Action可以替换
DAO自然也可以撤换!

banq
2007-04-13 10:49
实际上你的问题需要学习Evans DDD以后,就有答案,如果掌握Evans DDD建模,这个问题如果在纯设计领域讨论就是一个无聊的探讨。不要以为某个话题谈得越多越好,实际上你可能被绕进去了,为学日益,为道日损。

贫血和充血模型:

http://www.jdon.com/jivejdon/thread/31369.html

Dao属于Evans DDD的Respository 仓储:

http://www.jdon.com/mda/ddd.html

[该贴被banq于2007年04月13日 10:54修改过]

wlmouse
2007-04-13 11:55
benq,听您的话多半感觉像论禅。我也知道问题有些无聊,确实是自己被绕进去了。
昨天晚上又想了一下。决定把代理类扔掉。代理类中的功能用AOP解决。
这接口+AOP我觉得可以看作应用层。原来想的就是领域层该怎么办?原来的想法是把业务逻辑写道HQL中去,因为这些服务基本上都是持久化服务,业务大多都是查询、删除或者保存某个对象。日后如果框架变化就把整个类换掉,IOC配置里一改就可以了。
现在看来确实是领域层和数据层掺和到一起去了。之所以这样,我觉得可能是我以前只用Hibernate处理事务造成的吧。
不过如果把所有逻辑业务彻底和数据层独立的话,我该怎么处理领域层的事务呀?这个以前可没搞过。
比如,论坛里,某人发了一张帖子。系统把这张帖子保存下来的时候,同时给这个人加分。现在问题来了。
以前我是使用的Hibernate处理事务。Session打开,开始事务,session.save(帖子),用户加分,session.update(用户),事务提交,Session关闭。
业务逻辑和Hibernate操作混在一起。因为如果用户加分失败的话,需要和保存帖子操作一起回滚。
以前参与写的项目,是建立一个Dao层,把这些都封到Dao的一个方法里头去。
中间的领域层实际上只是一个代理。除了调Dao的方法,一个业务逻辑代码也没有。一个领域层方法对应一个Dao的方法,方法实现就一句,Dao.方法。出现两句的地方几乎没有。
所以,这次才会提出这个问题。
如果在领域层写业务,把Hibernate从领域层隔离出去的话,我该如何保证事务?
比如,领域层一个方法内要执行如下:持久层.保存(帖子),用户加分,持久层.保存(用户)。如果中间出错,需要回滚,我该怎么回滚?一个方法里有两个事务,如果保存用户出错,保存帖子的事务已经提交了,我该怎么办?用什么方式处理?EJB暂不考虑,我这个项目得能在Tomcat单机上跑。

banq
2007-04-13 12:57
>我该怎么处理领域层的事务呀?
JTA事务,事务不是只有数据库事务,而且数据库事务是底层事务,应用更多的是JTA事务,JTA是J2EE一部分,如何使用JTA可见JiveJdon3的messageService中相关代码。JTA不属于EJB,Spring等框架或无框架都可以使用JTA的。

wlmouse
2007-04-13 14:36
多谢了。上午去别的网站搜了一下。看到一篇文章说Dao里不要写事务。最佳实践是一次请求对应一次事务。事务可以在模型那里用手工编码或声明。Dao里写事务是反模式。如果一次请求执行很多Dao方法的话会产生很多事务。如果再加上模型的事务,等于一个大事务套了很多小事务。超级慢。我这就去看看如何在Web容器上配置JTA。或者看看Spring的声明性事务如何?

[该贴被wlmouse于2007年04月13日 14:51修改过]

猜你喜欢