浏览 2872 次
锁定老帖子 主题:服务器端分包结构回顾
精华帖 (0) :: 良好帖 (1) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2008-10-26
所以大部分项目看起来像下面这个样子分包: action service dao domain exception util 最近做的这个项目也采用了类似的结构, 其中service和dao的关系是一个老生常谈的问题, dao只对数据访问进行隔离,比如:Hibernate过时了,我们需要按一套全新的持久化方案,只需把Dao的实现类替换掉就行了。 service包括所有的业务逻辑,使用dao存取数据,并向Action功能提供服务。 然而,大部分企业应用中,业务逻辑就是对数据库的操作, 所以就出现了大量的service变成了dao的代理, 为此,有人提出,如果只是简单数据操作,action可以直接调用dao,因为同样保持着单向依赖。 但是,允许这样做后,dao函数的粒度较小,action变相的成了业务逻辑处理中心。 还有一个问题是,复杂的SQL语句,是业务还是数据操作?该放在dao,还是service? 其实放在dao或service, 都能说得通, 但我觉得应该放在service, SQL语句本身是业务逻辑,只是执行它的应该是数据操作接口, 如果dao只是作为数据操作接口,在现在数据自动映射处理框架的面前,是否有必要存在? 我比较赞同统一dao接口为一个特殊的服务, 如:PersistentService 持久化服务接口: public interface PersistentService extends Service { void save(Entity entity); void batchSave(Collection<Entity> entities); void update(Entity entity); void batchUpdate(Collection<Entity> entities); void saveOrUpdate(Entity entity); void batchSaveOrUpdate(Collection<Entity> entities); void remove(Entity entity); void batchRemove(Collection<Entity> entities); void remove(Class<?> entityClass, Long id); void batchRemove(Class<?> entityClass, Collection<Long> entityIds); Entity get(Entity entity); Entity get(Class<?> entityClass, Long id); Entity get(Class<?> entityClass, String property, Serializable value); Collection<Entity> find(Entity entity); Collection<Entity> find(Class<?> entityClass, String property, Serializable value); Collection<Entity> find(String query); Page<Entity> findPage(Entity entity); Page<Entity> findPage(Class<?> entityClass, String property, Serializable value); Page<Entity> findPage(String query); ...... } 然后,实现不同ORM框架的映射,如: public class HibernatePersistentService implements PersistentService { ...... } 或者SQL映射框架,如: public class IbatisPersistentService implements PersistentService { ...... } 或者非数据库持久化,如: public class XmlPersistentService implements PersistentService { ...... } 然后,在其它业务类服务基类中缺省由框架自动注入持久化服务: public abstract class AbstractService implements Service { /** * 日志输出接口 */ protected final Logger logger = LoggerFactory.getLogger(getClass()); /** * 持久化服务 */ protected PersistentService persistentService; // IoC注入接口 public void setPersistentService(PersistentService persistentService) { this.persistentService = persistentService; } } 业务类服务中使用如: public class UserServiceImpl extends AbstractService implements UserService { public User login(String username, String password) { // 直接使用持久化服务接口 User user = persistentService.get(User.class, "username" username); .... } } 这样统一后, service表示无状态的服务模型,服务可以再依赖服务,并且像邮件发送等也应该成为服务,而不是util工具。 action表示有状态的功能模型,代表一个用户可具体操作的功能。 模块间服务模型共享,并定义好依赖关系。 模块间功能模型使用名称空间相互区隔,互不干扰。 如: 雇员管理服务:包括雇员增删改查接口,数据一致性检查等。 雇员管理功能:包括新增雇员的界面,界面控制,数据传输等。 提成管理功能,也可依赖雇员管理服务,通过服务获取提成雇员的信息。 但提成管理功能却不会依赖雇员管理功能,因为它不关心雇员信息是怎么维护的。 如果雇员信息是从HR系统同步过来的,那样就只需要雇员管理服务,而不需要雇员管理功能,或者同步过程就是雇员管理功能。 所以服务模型和功能模型应该分别打成jar包,便于部署。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2008-10-26
javatar 写道 dao只对数据访问进行隔离,比如:Hibernate过时了,我们需要按一套全新的持久化方案,只需把Dao的实现类替换掉就行了。
这句话我总认为是听起来很美,不知道有没有人真正从中受益过。 如果hibernate过时了,那么我们开发的软件是否之前已经过时了呢。 真正要换掉dao层的时候,我想可能也不会像想象中那么简单的,其实DAO的代码相对倒是简单,更复杂的在于底层技术的一些细节。 甚至接口都要变化。 javatar 写道 还有一个问题是,复杂的SQL语句,是业务还是数据操作?该放在dao,还是service? 其实放在dao或service, 都能说得通, 但我觉得应该放在service, SQL语句本身是业务逻辑,只是执行它的应该是数据操作接口, 这个问题就更加复杂了,如果我们吧复杂查询放在DAO,那么我们的Service可就真的成了一个DAO的代理了,鸡勒。 如果我们放在service层,那么以前承诺的DAO层的可替换涉及也就落空了。你hibernate的HQL切换成其他查询语言,这个工作量可比我们换掉dao的代码复杂的多。 说一下我的做法。 DAO设计的时候给一个约定:只允许命名查询。 查询接口事制定查询名称和参数集合。这样,虽然查询还是在DAO做的,但是不是那种一个查询一个方法的方式。 这样做的好处就是Service不再像一个代理了。而DAO层也做了该做的事情。 还有一个好处就是,这样的DAO是可以自动生成的。 更多细节可以参看以前写的一个给予xdoclet的代码生成工具: http://code.google.com/p/txdoc/downloads/list http://txdoc.googlecode.com/svn/trunk/codegen/ 这个项目虽然有点明日黄花了,一些想法还是有点参考价值。 |
|
返回顶楼 | |
发表时间:2008-10-28
sql写在service还是dao,个人更倾向于写在dao,service操作都是面向对象的,传到dao的也是一个pojo对象。这样对于简单的crud,service确实会退化为一个dao的代理,而对于复杂的业务逻辑,涉及到多个表的操作的时候,复杂sql写在dao层,service看起来更加简洁。
|
|
返回顶楼 | |
发表时间:2008-10-30
其实 DAO 确实应该只是接口,其实我觉得根本不应该叫 “DAO”,而应该叫 Persistence。因为持久数据的方式有很多种,数据库只是其中一个。
俺赞同梁兄的设计 |
|
返回顶楼 | |
发表时间:2008-10-30
实际应用中,只有一种DaoImpl,什么HibernateDaoImpl,IbatisDaoImpl是不存在的.
所以实际开发中,我是No Dao Interface. |
|
返回顶楼 | |
发表时间:2008-11-01
其实怎么样设计都可以,主要考虑现实中的需要,Dao模式来源于《J2EE核心模式》,其主要目的是分离(或透明化)主动域实体(或充血模型)的持久化过程,在领域驱动设计中,Service + Dao的设计也可以作为“防腐战略”设计的一部分,自然有它的合理性,但实际很多时候,不需要这样的“过度”设计,因为通常项目的工期都很紧,我们有时候以快速开发为主,如果你觉得JSP + JavaBean + JDBC的方式更好,我也不反对。
|
|
返回顶楼 | |
发表时间:2008-11-05
Service中操作的是对象,而DAO操作的是数据库.
|
|
返回顶楼 | |
发表时间:2008-11-05
这个好像只能O/R mapping这样用。对象数据库没用过,应该也可以。
但是spring jdbc template, 或者 jdbc就不行。 |
|
返回顶楼 | |
发表时间:2008-11-05
Entity get(Class<?> entityClass, Long id);
为啥不是 Entity get(Class<?> entityClass, Object id); |
|
返回顶楼 | |
发表时间:2008-11-06
只是举例,可以改为:
Entity get(Class<?> entityClass, Serializable id); |
|
返回顶楼 | |