- 浏览: 1681315 次
- 性别:
- 来自: 杭州699号
文章分类
最新评论
-
莫莫摸:
为什么不用dubbo
RCP数据传输模型回顾 -
大胡子爸爸:
String, Class 都实现了Serializable接 ...
RPC框架几行代码就够了 -
lss598018587:
谢谢大神分享,比起新手看复杂的dubbo框架还不如看大神的这一 ...
RPC框架几行代码就够了 -
15606915740:
你好,请问一下。<dubbo:consumer filt ...
Dubbo文档 -
joqk12345:
...
一些设计上的基本常识
现在很多的Java应用都采用Eric在《DDD》中提出的域分层结构,
所以大部分项目看起来像下面这个样子分包:
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
持久化服务接口:
然后,实现不同ORM框架的映射,如:
或者SQL映射框架,如:
或者非数据库持久化,如:
然后,在其它业务类服务基类中缺省由框架自动注入持久化服务:
业务类服务中使用如:
这样统一后,
service表示无状态的服务模型,服务可以再依赖服务,并且像邮件发送等也应该成为服务,而不是util工具。
action表示有状态的功能模型,代表一个用户可具体操作的功能。
模块间服务模型共享,并定义好依赖关系。
模块间功能模型使用名称空间相互区隔,互不干扰。
如:
雇员管理服务:包括雇员增删改查接口,数据一致性检查等。
雇员管理功能:包括新增雇员的界面,界面控制,数据传输等。
提成管理功能,也可依赖雇员管理服务,通过服务获取提成雇员的信息。
但提成管理功能却不会依赖雇员管理功能,因为它不关心雇员信息是怎么维护的。
如果雇员信息是从HR系统同步过来的,那样就只需要雇员管理服务,而不需要雇员管理功能,或者同步过程就是雇员管理功能。
所以服务模型和功能模型应该分别打成jar包,便于部署。
这句话我总认为是听起来很美,不知道有没有人真正从中受益过。
如果hibernate过时了,那么我们开发的软件是否之前已经过时了呢。
真正要换掉dao层的时候,我想可能也不会像想象中那么简单的,其实DAO的代码相对倒是简单,更复杂的在于底层技术的一些细节。
甚至接口都要变化。
还有一个问题是,复杂的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/
这个项目虽然有点明日黄花了,一些想法还是有点参考价值。
所以大部分项目看起来像下面这个样子分包:
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包,便于部署。
评论
9 楼
javatar
2008-11-06
只是举例,可以改为:
Entity get(Class<?> entityClass, Serializable id);
Entity get(Class<?> entityClass, Serializable id);
8 楼
laiseeme
2008-11-05
Entity get(Class<?> entityClass, Long id);
为啥不是
Entity get(Class<?> entityClass, Object id);
为啥不是
Entity get(Class<?> entityClass, Object id);
7 楼
jander
2008-11-05
这个好像只能O/R mapping这样用。对象数据库没用过,应该也可以。
但是spring jdbc template, 或者 jdbc就不行。
但是spring jdbc template, 或者 jdbc就不行。
6 楼
z494627
2008-11-05
Service中操作的是对象,而DAO操作的是数据库.
5 楼
javatar
2008-11-01
其实怎么样设计都可以,主要考虑现实中的需要,Dao模式来源于《J2EE核心模式》,其主要目的是分离(或透明化)主动域实体(或充血模型)的持久化过程,在领域驱动设计中,Service + Dao的设计也可以作为“防腐战略”设计的一部分,自然有它的合理性,但实际很多时候,不需要这样的“过度”设计,因为通常项目的工期都很紧,我们有时候以快速开发为主,如果你觉得JSP + JavaBean + JDBC的方式更好,我也不反对。
4 楼
超级潜水员
2008-10-30
实际应用中,只有一种DaoImpl,什么HibernateDaoImpl,IbatisDaoImpl是不存在的.
所以实际开发中,我是No Dao Interface.
所以实际开发中,我是No Dao Interface.
3 楼
yananay
2008-10-30
其实 DAO 确实应该只是接口,其实我觉得根本不应该叫 “DAO”,而应该叫 Persistence。因为持久数据的方式有很多种,数据库只是其中一个。
俺赞同梁兄的设计
俺赞同梁兄的设计
2 楼
jasin2008
2008-10-28
sql写在service还是dao,个人更倾向于写在dao,service操作都是面向对象的,传到dao的也是一个pojo对象。这样对于简单的crud,service确实会退化为一个dao的代理,而对于复杂的业务逻辑,涉及到多个表的操作的时候,复杂sql写在dao层,service看起来更加简洁。
1 楼
jindw
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/
这个项目虽然有点明日黄花了,一些想法还是有点参考价值。
发表评论
-
能力成长模型
2012-05-09 00:28 22683最近看了温伯格1986年出版的《技术领导之路》, 很老的书,讲 ... -
以HTTL为例讲讲模块分包&领域模型&扩展框架
2011-10-09 20:08 16459注:该博客内容已加入 ... -
使用Map参数的Webx3扩展
2011-08-28 02:10 5857因Webx3是开源的,所以把这个简单的Webx3扩展发在博客上 ... -
Netty内存泄露
2011-08-02 20:09 24872转于自己在公司的Blog: ... -
Grizzly和Netty以及Mina简单性能对比
2011-07-17 02:48 29618转于自己在公司的Blog: http://pt.alibaba ... -
RPC框架几行代码就够了
2011-07-14 00:34 89519转于自己在公司的Blog: http://pt.alibaba ... -
魔鬼在细节中
2011-05-24 14:50 32255转于自己在公司的Blog: ... -
Dubbo扩展点重构
2011-05-12 22:09 38768转于自己在公司的Blog: http://pt.alibaba ... -
配置设计
2011-03-09 23:41 23438转于自己在公司的Blog: ... -
[转]HTML5设计原理
2011-03-09 22:57 7661Jeremy Keith在 Fronteers 2010 ... -
Hessian序列化不设SerializerFactory性能问题
2010-12-27 11:38 6383转于自己在公司的Blog: http://pt.alibaba ... -
动态代理方案性能对比
2010-11-17 21:38 45686转于自己在公司的Blog: http://pt.alibaba ... -
防痴呆设计
2010-11-05 18:58 17519转于自己在公司的Blog: ... -
负载均衡扩展接口重构
2010-11-05 18:53 8637转于自己在公司的Blog: ... -
分布式服务框架常被质疑的价值
2010-11-05 18:52 5680转于自己在公司的Blog: http://pt.alibaba ... -
Hessian3.2.1在序列化32.5k字符串时的问题
2010-11-05 18:49 7122转于自己在公司的Blog: http://pt.alibaba ... -
一些设计上的基本常识
2010-07-05 19:28 27452转于自己在公司的Blog: ... -
谈谈扩充式扩展与增量式扩展
2010-06-12 19:46 19004转于自己在公司的Blog: http://pt.alibaba ... -
Scaling Architecture
2010-02-25 10:31 4057Scaling Second Life: http://p ... -
EBay SOA
2010-02-23 18:23 4743EBay SOA PPT
相关推荐
全志OTA客户端服务器端完整文档以及服务器端 客户端源代码(按文档操作验证可以使用) 提供OTA全套技术:包括客户端源码与服务器端配置,以及差分包生成方法。
结构加固专业分包合同.doc
钢结构厂房分包合同.pdf
LineBaseFrameDecoder 换行符解码器 DelimiterBaseFrameDecoder 定界符解码器
2.client端 将图片数据转换成字节数据 增加鉴权 进行分包发送 3.server端校验udp包的正确性(避免其他人发送的错误包被解析) 4.server端将收到的udp包进行合并 5.server端合并后正确的生成一张图片。 6.使用说明...
在stm32f407的平台下,进行TCP的服务器端数据收发
• 从分包结构能够大致了解App的功能。 • 高度模块化大大提高了代码的可读性及可维护性。 • 包与包之间耦合度降低,拆分、添加或删除功能模块变得简单。 • 更加抽象化、模块化,方便扩展和重用。
分包下支持独立的 static 目录,用来对静态资源进行分包。 uni-app内支持对微信小程序、QQ小程序、百度小程序分包优化,即将静态资源或者js文件放入分包内不占用主包大小。详情请参考:关于分包优化的说明 针对...
国家电网公司电力建设工程专业分包、劳务分包安全管理规定
钢结构分包合同模板.pdf
Tcp数据分包传输(socket数据分包传输),将加载到内存的大文件进行分包传输,解决socket在传输较大数据时候缓冲区空间小于数据流大小时候导致接收时候无法接收全部数据而引起数据流丢失。 传输方式是将内存中的大...
编辑器分包001编辑器分包001编辑器分包001编辑器分包001
IOCP分包.rar
APK分包工具
jaca视频教程 jaca游戏服务器端开发 Netty NIO AIO Mina视频教程 课程目录: 一、Netty快速入门教程 01、第一课NIO 02、第二课netty服务端 03、第三课netty客户端 04、第四课netty线程模型源码分析(一) 05、...
主体结构劳务分包合同模板.doc
建设工程转包分包法律风险防控,建设工程转包分包法律风险防控PPT,建设工程转包分包法律风险防控课件
laya分包简单教程(无需积分和付费)
源代码分包详解源代码分包详解源代码分包详解源代码分包详解源代码分包详解源代码分包详解