- 浏览: 383436 次
- 性别:
文章分类
最新评论
-
wjw103:
You are using old notation for ...
Struts2 入门实例代码 -
hhb19900618:
你好 你这个工程压缩包是不是有问题啊?根本不能导入?
Struts2 入门实例代码 -
it爱:
[list][*]dsadsa[*]dsadsa[*]dsad ...
Spring AOP 学习小结 -
youjianbo_han_87:
和 weblogic 有个毛线关系???????
Weblogic下的自动任务 -
hua839:
是用SmartUpload进行文件上传
Service 层的代码
DAO 层的代码
迷惑的是在上面的代码中,Service 并没有什么业务逻辑,似乎可有可无,是否上面的代码可以将Service层省略,直接在DAO层操作和事务拦截,只有涉及到具体业务逻辑的时候使用Service,当然这会造成Controller和DAO层之间的紧耦合,大家在项目中遇到如上情况都是如何做的?
我记得这个问题在阎宏在《java与模式》曾经讲过:要尽量使用合成/聚合,尽量不使用继承。
而在我们这个问题上刚好是最佳注脚
Dao跟service本身就不是在一个层次上 让他们继承实在有些牵强,而采用合成/聚合则使dao层和service层有更松散的耦合,所以就耦合性来讲 采用合成聚合方式更为合理。
但是采用合成聚合方式会在xxxService类中多出一个daoHelper对象,好像是增加了复杂度。
其实只要明白了这个道理就行了,怎么简单怎么来啦
同意这种方式
我曾经在项目中这样用过
SqlMapClientDaoSupport 是 org.springframework.orm.ibatis.support.SqlMapClientDaoSupport;
我的代码很复杂吗?可能我没有表述清楚.
所有的Service继承AbstractService,
所有的Dao继承AbstractDao,
CRUD的简单操作不用在Service和Dao层定义,简单的Query直接写在Service中.
复杂的逻辑如isChecked(),count等直接和业务逻辑相关又不是简单的CRUD操作,才放置在DAO中.
你有没有想过,写 一些简单的业务逻辑是可以放在DAO里,但要是整个系统很大,业务逻辑很复杂,你会怎么处理呢,我现在在做交行的基金托管项目,业务出奇的复杂,涉及了个方面的知识,有财务会计,证券,股票,基金等等,我觉得还是分开来比较好!!
因为service层已经对CRUD进行了很好的封装了阿,复杂的业务逻辑为什么不可以?CRUD有了,复杂的逻辑需要的原子操作已经有了阿.
如果系统业务简单
可以抽象出通用的dao层(也就一个类)
让业务层继承通用的dao
看了大家的讨论,我现在的想法是干脆将DAO层舍弃,直接由Service来承担,这样最简单.
为什么不考虑这里用泛型?
范型意味着多个method的声明,那用不用范型没有区别.
为什么不考虑这里用泛型?
过度设计!
真遇到这种变态需求变化只改变service层就行了??
例如:原来有个客户保存的dao方法,被一个service方法调用,同时这个dao方法直接暴露给前台,这时如果直接暴露的方法要预先做个判断客户的某个条件,而原先引用这个dao的service方法不需要这个逻辑,难道直接修改这个dao方法吗?
难道不能按照需要增加个中间层么?
系统开始可能觉的这样比较烦人,但是要有长远的考虑。
先跑起来,而且要简单
将如上代码放入DAO的超类中,这样我每一个DAO就不需要重复写这些功能雷同的代码!不知道有什么不合适之处.
无论怎么简化dao层,dao对外的接口是不变的,最终业务层还是要是调用dao层的方法,还是会出现楼主的问题
我觉得既然项目业务比较简单,省掉业务层也未尝不可, 在web层直接调用dao 。
如果遇到业务操作就写在dao层,或者web层。
对的,其实除了简单的crud操作之外,还与很多query之类的操作,感觉通过Service 就是走过场!
我在 DAO 层所简化的也只是在DAO层把最基本的crud操作简单封装了一下,避免在所有的dao中进行crud的编写!
看来这是一个在简单和规范之间进行的选择,要简单,直接dao,要规范,加层service.
将如上代码放入DAO的超类中,这样我每一个DAO就不需要重复写这些功能雷同的代码!不知道有什么不合适之处.
无论怎么简化dao层,dao对外的接口是不变的,最终业务层还是要是调用dao层的方法,还是会出现楼主的问题
我觉得既然项目业务比较简单,省掉业务层也未尝不可, 在web层直接调用dao 。
如果遇到业务操作就写在dao层,或者web层。
现在的业务基本都是这种简单的情况,因为复杂的方式要求写存储过程. 简单情况如何合并?不是很理解
简单情况直接在action里调持久层代码
如
JdbcUtil.save(objet);
JdbcUtil.update(objet);
JdbcUtil.query(sql,params);
JdbcUtil可以是对hibernate,ibatis,spring jdbctemplate,dbutil,jdbc等的封装
如果比较复杂,涉及多个实体操作,事务之类的,
再整个service出来,
public class GeneralService extends AbstractService { private GeneralDao generalDao; public void setGeneralDao(GeneralDao generalDao) { this.generalDao = generalDao; } public void saveResourceSale(ResourceItemFormbean resourceItem) throws Exception { generalDao.saveResourceSale(resourceItem); } public List selectTodayResource(Map params) throws Exception { return generalDao.selectTodayResource(params); } public List selectTdPrintInfo(Integer ddid, Integer linkmanid) throws Exception { return generalDao.selectTdPrintInfo(ddid, linkmanid); } public List selectTdPrintItems(Integer ddid) throws Exception { return generalDao.selectTdPrintItems(ddid); } public List selectTodayBuy(Map params) throws Exception { return generalDao.selectTodayBuy(params); } public List selectStockKgzy(Integer ptid, Integer prodid, Integer cmdeptid,Integer page) throws Exception { return generalDao.selectStockKgzy(ptid, prodid, cmdeptid,page); } public List selectStockXqzy(Integer ptid, Integer prodid, Integer cmdeptid, Integer page) throws Exception { return generalDao.selectStockXqzy(ptid, prodid, cmdeptid, page); } public void deletePublishedResource(Integer pkid) throws Exception { generalDao.deletePublishedResource(pkid); } public void saveXqResourcePublish(XqZyfbModel data) throws Exception { generalDao.saveXqResourcePublish(data); } public XqZyfbModel selectXqResourceDetail(Integer pkid) throws Exception { return generalDao.selectXqResourceDetail(pkid); } }
DAO 层的代码
public class GeneralDao extends AbstractDao { public void saveResourcePublish(ZyfbModel data) throws Exception { getSqlMapClientTemplate().update("MainProcedure.saveResourcePublish", data); } public void updateResourcePublish(ZyfbModel data) throws Exception { getSqlMapClientTemplate().update("MainProcedure.updateResourcePublish", data); } public void deletePublishedResource(Integer pkid) throws Exception { getSqlMapClientTemplate().update("MainProcedure.deletePublishedResource", pkid); } public List selectStockXqzy(Integer ptid, Integer prodid, Integer cmdeptid, Integer page) throws Exception { Map params = new HashMap(); params.put("ptid", ptid); params.put("prodid", prodid); params.put("cmdeptid", cmdeptid); params.put("row", new Integer(15)); params.put("page", page); return getSqlMapClientTemplate().queryForList( "MainProcedure.selectStockXqzy", params); } public void saveXqResourcePublish(XqZyfbModel data) throws Exception { getSqlMapClientTemplate().update("MainProcedure.saveXqResourcePublish", data); } public XqZyfbModel selectXqResourceDetail(Integer pkid) throws Exception { return (XqZyfbModel) getSqlMapClientTemplate().queryForObject( "MainProcedure.selectXqResourceDetail", pkid); } }
迷惑的是在上面的代码中,Service 并没有什么业务逻辑,似乎可有可无,是否上面的代码可以将Service层省略,直接在DAO层操作和事务拦截,只有涉及到具体业务逻辑的时候使用Service,当然这会造成Controller和DAO层之间的紧耦合,大家在项目中遇到如上情况都是如何做的?
评论
28 楼
xuni
2007-03-02
偶尔翻到这儿,我的解决办法是
public class BaseService{ protected BaseDAO baseDAO; protected void saveOrUpdate(Object a){ baseDAO.saveOrUpdate(a); } //.... //get/set dao } public class ConcreteService extends BaseService{ } public class ViewBean{ private ConcreteService service; private ConcreteModel model; public String save(){ service.saveOrUpdate(model); } //... //get/set service }
27 楼
xuni
2007-03-02
偶尔翻到这儿,我的解决办法是
public class BaseService{ protected BaseDAO baseDAO; protected void saveOrUpdate(Object a){ baseDAO.saveOrUpdate(a); } //.... //get/set dao } public class ConcreteService extends BaseService{ } public class ViewBean{ private ConcreteService service; private ConcreteModel model; public String save(){ service.saveOrUpdate(model); } //... //get/set service }
26 楼
xly_971223
2007-02-26
jamesby 写道
目前有一个想法,前面有人说过用DaoHelper,不过我比较不喜欢直接调用Helper类,因此有这样一个想法:
将DaoHelper注入到AbstractService 中,然后针对DaoHelper的每一个方法调用在AbstractService 进行代理,也就是说所有的操作都需要通过Service不可以绕行,而且这样也不需要Service继承Dao,Service继承Dao总是感觉很奇怪。
当然缺点就是对于每一个Service都需要注入这样一个DaoHelper。
将DaoHelper注入到AbstractService 中,然后针对DaoHelper的每一个方法调用在AbstractService 进行代理,也就是说所有的操作都需要通过Service不可以绕行,而且这样也不需要Service继承Dao,Service继承Dao总是感觉很奇怪。
当然缺点就是对于每一个Service都需要注入这样一个DaoHelper。
我记得这个问题在阎宏在《java与模式》曾经讲过:要尽量使用合成/聚合,尽量不使用继承。
而在我们这个问题上刚好是最佳注脚
Dao跟service本身就不是在一个层次上 让他们继承实在有些牵强,而采用合成/聚合则使dao层和service层有更松散的耦合,所以就耦合性来讲 采用合成聚合方式更为合理。
但是采用合成聚合方式会在xxxService类中多出一个daoHelper对象,好像是增加了复杂度。
其实只要明白了这个道理就行了,怎么简单怎么来啦
25 楼
jamesby
2007-02-26
目前有一个想法,前面有人说过用DaoHelper,不过我比较不喜欢直接调用Helper类,因此有这样一个想法:
将DaoHelper注入到AbstractService 中,然后针对DaoHelper的每一个方法调用在AbstractService 进行代理,也就是说所有的操作都需要通过Service不可以绕行,而且这样也不需要Service继承Dao,Service继承Dao总是感觉很奇怪。
当然缺点就是对于每一个Service都需要注入这样一个DaoHelper。
将DaoHelper注入到AbstractService 中,然后针对DaoHelper的每一个方法调用在AbstractService 进行代理,也就是说所有的操作都需要通过Service不可以绕行,而且这样也不需要Service继承Dao,Service继承Dao总是感觉很奇怪。
当然缺点就是对于每一个Service都需要注入这样一个DaoHelper。
24 楼
xly_971223
2007-02-26
jamesby 写道
目前我的BaseDao是这样的
然后BaseService这样
省略Dao层!
public abstract class AbstractDao extends SqlMapClientDaoSupport { protected final static Log log = LogFactory.getLog(AbstractDao.class); public int updateEntity(Object entity, String statementId) throws Exception { return getSqlMapClientTemplate().update(statementId, entity); } public int insertEntity(Object entity, String statementId) throws Exception { return getSqlMapClientTemplate().update(statementId, entity); } public int deleteEntity(Object entity, String statementId) throws Exception { return getSqlMapClientTemplate().delete(statementId, entity); } public Object queryForObject(Integer pkid, String statementid) throws Exception { return getSqlMapClientTemplate().queryForObject(statementid, pkid); } public List queryForList(Object params, String statementid) throws Exception { return getSqlMapClientTemplate().queryForList(statementid, params); } }
然后BaseService这样
public abstract class AbstractService extends AbstractDao { }
省略Dao层!
同意这种方式
我曾经在项目中这样用过
23 楼
jamesby
2007-02-24
基于上面的讨论,可以归纳为三种实现方式
第一种:BaseService不需要继承BaseDao
各种query,update等操作在Service和Dao中都做声明。Service不需要同BaseDao偶合过紧密,这也是第一页代码的实现方式。
第二种:BaseService不需要继承BaseDao,退化使用Dao层
各种query,update等操作在Service做声明,在Dao层不作声明,既Service直接调用BaseDao的queryForList,queryForObject等方法,由Service确定statementid。
第三种:BaseService需要继承BaseDao,退化使用Service和Dao
各种query,update等无业务逻辑的操作既不在Service中声明,也不在Dao中声明,Controller直接构造参数,确定statementid,然后调用BaseService的queryForList,queryForObject等方法.
本来采用第一种方式实现,发现代码过于繁琐;
后采用第二种,发现仍有简化空间
目前采用第三种,Service和Dao中几乎不用写任何代码,实现为第一位,项目时间紧。
第一种:BaseService不需要继承BaseDao
各种query,update等操作在Service和Dao中都做声明。Service不需要同BaseDao偶合过紧密,这也是第一页代码的实现方式。
第二种:BaseService不需要继承BaseDao,退化使用Dao层
各种query,update等操作在Service做声明,在Dao层不作声明,既Service直接调用BaseDao的queryForList,queryForObject等方法,由Service确定statementid。
第三种:BaseService需要继承BaseDao,退化使用Service和Dao
各种query,update等无业务逻辑的操作既不在Service中声明,也不在Dao中声明,Controller直接构造参数,确定statementid,然后调用BaseService的queryForList,queryForObject等方法.
本来采用第一种方式实现,发现代码过于繁琐;
后采用第二种,发现仍有简化空间
目前采用第三种,Service和Dao中几乎不用写任何代码,实现为第一位,项目时间紧。
22 楼
jamesby
2007-02-23
basicbest 写道
这样写法的用意是怎样?
AbstractDao 为什么要 extends 一个 SqlMapClientDaoSupport ?
SqlMapClientDaoSupport是什么?
看代码还是太detail,没有办法overview,虽然从直觉上我觉得你现在这样做有些复杂了,但是还没有充分的直接的理由下结论。能否把架构图展示一下先?
AbstractDao 为什么要 extends 一个 SqlMapClientDaoSupport ?
SqlMapClientDaoSupport是什么?
看代码还是太detail,没有办法overview,虽然从直觉上我觉得你现在这样做有些复杂了,但是还没有充分的直接的理由下结论。能否把架构图展示一下先?
SqlMapClientDaoSupport 是 org.springframework.orm.ibatis.support.SqlMapClientDaoSupport;
我的代码很复杂吗?可能我没有表述清楚.
所有的Service继承AbstractService,
所有的Dao继承AbstractDao,
CRUD的简单操作不用在Service和Dao层定义,简单的Query直接写在Service中.
复杂的逻辑如isChecked(),count等直接和业务逻辑相关又不是简单的CRUD操作,才放置在DAO中.
21 楼
basicbest
2007-02-23
这样写法的用意是怎样?
AbstractDao 为什么要 extends 一个 SqlMapClientDaoSupport ?
SqlMapClientDaoSupport是什么?
看代码还是太detail,没有办法overview,虽然从直觉上我觉得你现在这样做有些复杂了,但是还没有充分的直接的理由下结论。能否把架构图展示一下先?
AbstractDao 为什么要 extends 一个 SqlMapClientDaoSupport ?
SqlMapClientDaoSupport是什么?
看代码还是太detail,没有办法overview,虽然从直觉上我觉得你现在这样做有些复杂了,但是还没有充分的直接的理由下结论。能否把架构图展示一下先?
20 楼
jamesby
2007-02-23
目前我的BaseDao是这样的
然后BaseService这样
省略Dao层!
public abstract class AbstractDao extends SqlMapClientDaoSupport { protected final static Log log = LogFactory.getLog(AbstractDao.class); public int updateEntity(Object entity, String statementId) throws Exception { return getSqlMapClientTemplate().update(statementId, entity); } public int insertEntity(Object entity, String statementId) throws Exception { return getSqlMapClientTemplate().update(statementId, entity); } public int deleteEntity(Object entity, String statementId) throws Exception { return getSqlMapClientTemplate().delete(statementId, entity); } public Object queryForObject(Integer pkid, String statementid) throws Exception { return getSqlMapClientTemplate().queryForObject(statementid, pkid); } public List queryForList(Object params, String statementid) throws Exception { return getSqlMapClientTemplate().queryForList(statementid, params); } }
然后BaseService这样
public abstract class AbstractService extends AbstractDao { }
省略Dao层!
19 楼
jamesby
2007-02-23
zwchen 写道
不妨看看我以前写的一篇文章,里面有代码和guide,http://zwchen.iteye.com/admin/show/47085
对于你的疑问,我的看法是(摘自原文):
分层架构:分层架构有助于将大系统分解成子任务,每个子任务限制在一个特定的层次上,层间从上到下依赖,从下到上是松耦合。TCP/IP分层模型是它的最好证明。正如OSI 7层模型的实用模型是TCP/IP 4层模型。MiniFramework中,用户接触到的是两层:表示层和业务层,是J2EE和.NET架构的一种折中。在用MiniFramework开发时,持久层被封装起来,成为一些简单的Helper类,不是独立的一层。
之所以我去掉了持久层,只保留的dao helper,是因为,我发现业务比较简单的系统,往往开发人员喜欢在持久层里面写所有的业务,service层只是dao的一个delegate,非常 thin。要是这样,我就干脆去掉一层算了,这便是dao helper的由来。
严格的分层,可以让表示层的UI用Dreamweaver开发,业务层容器外测试,实现敏捷开发。
接口:在分层模型中,一般都非常强调接口,因为可以让上层只依赖于下层的接口,而不是实现,这样实现可以任意替换和变更,在网络开发,特别是和协议打交道的时候,我们会体会到这种设计的优雅。另外,在组件式开发中,我们也倾向于提供接口。
但是,应用MiniFramework,我们倾向于纵向开发,也就是说,某个模块从表示层到持久层都是一人开发,而不是横向:表示层的去调用业务层开发人员的业务层。这时候,纵向开发就不太适合用接口了,因为接口规范完全由本人把握。这时接口很可能只会带来臃肿,和难维护,一点改动往往牵一动百。当然,在某些情况,如开发Mock测试,Web Services,接口还是很有必要。另外,有人说,我用接口可以实现任意层替换啊?譬如我现在用Hibernate,以后换成IBatis。这完全是一个谎言,至少我看到的大多数应用,将Hibernate换成IBatis的成本绝不亚于重新开发,因为耦合太大。另外,我有个疑问:需要更换的可能性有 1%吗?
个人觉得,接口比较适合于系统软件开发,而不是商业软件开发;而抽象类的继承机制比较适合商业软件开发,而不是系统软件开发。为了复用,系统软件开发倾向于组合,而不是继承。
其实,对于业务逻辑简单的系统,省略掉一层我觉得非常有必要,当然前提是我选择了简单而不是规范,就如楼上所说,如此thin 的 service层真的没有必要!
对于你的疑问,我的看法是(摘自原文):
引用
分层架构:分层架构有助于将大系统分解成子任务,每个子任务限制在一个特定的层次上,层间从上到下依赖,从下到上是松耦合。TCP/IP分层模型是它的最好证明。正如OSI 7层模型的实用模型是TCP/IP 4层模型。MiniFramework中,用户接触到的是两层:表示层和业务层,是J2EE和.NET架构的一种折中。在用MiniFramework开发时,持久层被封装起来,成为一些简单的Helper类,不是独立的一层。
之所以我去掉了持久层,只保留的dao helper,是因为,我发现业务比较简单的系统,往往开发人员喜欢在持久层里面写所有的业务,service层只是dao的一个delegate,非常 thin。要是这样,我就干脆去掉一层算了,这便是dao helper的由来。
严格的分层,可以让表示层的UI用Dreamweaver开发,业务层容器外测试,实现敏捷开发。
接口:在分层模型中,一般都非常强调接口,因为可以让上层只依赖于下层的接口,而不是实现,这样实现可以任意替换和变更,在网络开发,特别是和协议打交道的时候,我们会体会到这种设计的优雅。另外,在组件式开发中,我们也倾向于提供接口。
但是,应用MiniFramework,我们倾向于纵向开发,也就是说,某个模块从表示层到持久层都是一人开发,而不是横向:表示层的去调用业务层开发人员的业务层。这时候,纵向开发就不太适合用接口了,因为接口规范完全由本人把握。这时接口很可能只会带来臃肿,和难维护,一点改动往往牵一动百。当然,在某些情况,如开发Mock测试,Web Services,接口还是很有必要。另外,有人说,我用接口可以实现任意层替换啊?譬如我现在用Hibernate,以后换成IBatis。这完全是一个谎言,至少我看到的大多数应用,将Hibernate换成IBatis的成本绝不亚于重新开发,因为耦合太大。另外,我有个疑问:需要更换的可能性有 1%吗?
个人觉得,接口比较适合于系统软件开发,而不是商业软件开发;而抽象类的继承机制比较适合商业软件开发,而不是系统软件开发。为了复用,系统软件开发倾向于组合,而不是继承。
lingxu_lingxu 写道
你有没有想过,写 一些简单的业务逻辑是可以放在DAO里,但要是整个系统很大,业务逻辑很复杂,你会怎么处理呢,我现在在做交行的基金托管项目,业务出奇的复杂,涉及了个方面的知识,有财务会计,证券,股票,基金等等,我觉得还是分开来比较好!!
因为service层已经对CRUD进行了很好的封装了阿,复杂的业务逻辑为什么不可以?CRUD有了,复杂的逻辑需要的原子操作已经有了阿.
温柔一刀 写道
如果系统业务简单
可以抽象出通用的dao层(也就一个类)
让业务层继承通用的dao
看了大家的讨论,我现在的想法是干脆将DAO层舍弃,直接由Service来承担,这样最简单.
DigitalSonic 写道
为什么不考虑这里用泛型?
范型意味着多个method的声明,那用不用范型没有区别.
18 楼
zwchen
2007-02-22
不妨看看我以前写的一篇文章,里面有代码和guide,http://zwchen.iteye.com/blog/47085
对于你的疑问,我的看法是(摘自原文):
分层架构:分层架构有助于将大系统分解成子任务,每个子任务限制在一个特定的层次上,层间从上到下依赖,从下到上是松耦合。TCP/IP分层模型是它的最好证明。正如OSI 7层模型的实用模型是TCP/IP 4层模型。MiniFramework中,用户接触到的是两层:表示层和业务层,是J2EE和.NET架构的一种折中。在用MiniFramework开发时,持久层被封装起来,成为一些简单的Helper类,不是独立的一层。
之所以我去掉了持久层,只保留的dao helper,是因为,我发现业务比较简单的系统,往往开发人员喜欢在持久层里面写所有的业务,service层只是dao的一个delegate,非常 thin。要是这样,我就干脆去掉一层算了,这便是dao helper的由来。
严格的分层,可以让表示层的UI用Dreamweaver开发,业务层容器外测试,实现敏捷开发。
接口:在分层模型中,一般都非常强调接口,因为可以让上层只依赖于下层的接口,而不是实现,这样实现可以任意替换和变更,在网络开发,特别是和协议打交道的时候,我们会体会到这种设计的优雅。另外,在组件式开发中,我们也倾向于提供接口。
但是,应用MiniFramework,我们倾向于纵向开发,也就是说,某个模块从表示层到持久层都是一人开发,而不是横向:表示层的去调用业务层开发人员的业务层。这时候,纵向开发就不太适合用接口了,因为接口规范完全由本人把握。这时接口很可能只会带来臃肿,和难维护,一点改动往往牵一动百。当然,在某些情况,如开发Mock测试,Web Services,接口还是很有必要。另外,有人说,我用接口可以实现任意层替换啊?譬如我现在用Hibernate,以后换成IBatis。这完全是一个谎言,至少我看到的大多数应用,将Hibernate换成IBatis的成本绝不亚于重新开发,因为耦合太大。另外,我有个疑问:需要更换的可能性有 1%吗?
个人觉得,接口比较适合于系统软件开发,而不是商业软件开发;而抽象类的继承机制比较适合商业软件开发,而不是系统软件开发。为了复用,系统软件开发倾向于组合,而不是继承。
对于你的疑问,我的看法是(摘自原文):
引用
分层架构:分层架构有助于将大系统分解成子任务,每个子任务限制在一个特定的层次上,层间从上到下依赖,从下到上是松耦合。TCP/IP分层模型是它的最好证明。正如OSI 7层模型的实用模型是TCP/IP 4层模型。MiniFramework中,用户接触到的是两层:表示层和业务层,是J2EE和.NET架构的一种折中。在用MiniFramework开发时,持久层被封装起来,成为一些简单的Helper类,不是独立的一层。
之所以我去掉了持久层,只保留的dao helper,是因为,我发现业务比较简单的系统,往往开发人员喜欢在持久层里面写所有的业务,service层只是dao的一个delegate,非常 thin。要是这样,我就干脆去掉一层算了,这便是dao helper的由来。
严格的分层,可以让表示层的UI用Dreamweaver开发,业务层容器外测试,实现敏捷开发。
接口:在分层模型中,一般都非常强调接口,因为可以让上层只依赖于下层的接口,而不是实现,这样实现可以任意替换和变更,在网络开发,特别是和协议打交道的时候,我们会体会到这种设计的优雅。另外,在组件式开发中,我们也倾向于提供接口。
但是,应用MiniFramework,我们倾向于纵向开发,也就是说,某个模块从表示层到持久层都是一人开发,而不是横向:表示层的去调用业务层开发人员的业务层。这时候,纵向开发就不太适合用接口了,因为接口规范完全由本人把握。这时接口很可能只会带来臃肿,和难维护,一点改动往往牵一动百。当然,在某些情况,如开发Mock测试,Web Services,接口还是很有必要。另外,有人说,我用接口可以实现任意层替换啊?譬如我现在用Hibernate,以后换成IBatis。这完全是一个谎言,至少我看到的大多数应用,将Hibernate换成IBatis的成本绝不亚于重新开发,因为耦合太大。另外,我有个疑问:需要更换的可能性有 1%吗?
个人觉得,接口比较适合于系统软件开发,而不是商业软件开发;而抽象类的继承机制比较适合商业软件开发,而不是系统软件开发。为了复用,系统软件开发倾向于组合,而不是继承。
17 楼
lingxu_lingxu
2007-02-17
你有没有想过,写 一些简单的业务逻辑是可以放在DAO里,但要是整个系统很大,业务逻辑很复杂,你会怎么处理呢,我现在在做交行的基金托管项目,业务出奇的复杂,涉及了个方面的知识,有财务会计,证券,股票,基金等等,我觉得还是分开来比较好!!
16 楼
温柔一刀
2007-02-17
如果系统业务简单
可以抽象出通用的dao层(也就一个类)
让业务层继承通用的dao
可以抽象出通用的dao层(也就一个类)
让业务层继承通用的dao
15 楼
DigitalSonic
2007-02-16
jamesby 写道
xuni 写道
写一个service和DAO的基类不就成了吗,service中有一个BaseDAO的实例,service基类的save方法调用dao的save方法,
我一直以为Service层的接口声明应该是清晰,你这样所有的save,update,delete之类的参数都是Object类型的参数了!为什么不考虑这里用泛型?
14 楼
pikachu
2007-02-16
foxhon 写道
直接使用dao层是比较不合理的,dao层封装的通常是原子化的操作,业务层是组织业务逻辑的,目前service层可能只是简单的调用dao层的方法,不代表逻辑变化之后需要更加复杂的逻辑,这时不可能直接修改dao层,有可能破坏别的service方法对当前调用的dao的逻辑。
过度设计!
真遇到这种变态需求变化只改变service层就行了??
foxhon 写道
例如:原来有个客户保存的dao方法,被一个service方法调用,同时这个dao方法直接暴露给前台,这时如果直接暴露的方法要预先做个判断客户的某个条件,而原先引用这个dao的service方法不需要这个逻辑,难道直接修改这个dao方法吗?
难道不能按照需要增加个中间层么?
foxhon 写道
系统开始可能觉的这样比较烦人,但是要有长远的考虑。
先跑起来,而且要简单
13 楼
foxhon
2007-02-15
直接使用dao层是比较不合理的,dao层封装的通常是原子化的操作,业务层是组织业务逻辑的,目前service层可能只是简单的调用dao层的方法,不代表逻辑变化之后需要更加复杂的逻辑,这时不可能直接修改dao层,有可能破坏别的service方法对当前调用的dao的逻辑。
例如:原来有个客户保存的dao方法,被一个service方法调用,同时这个dao方法直接暴露给前台,这时如果直接暴露的方法要预先做个判断客户的某个条件,而原先引用这个dao的service方法不需要这个逻辑,难道直接修改这个dao方法吗?
系统开始可能觉的这样比较烦人,但是要有长远的考虑。
例如:原来有个客户保存的dao方法,被一个service方法调用,同时这个dao方法直接暴露给前台,这时如果直接暴露的方法要预先做个判断客户的某个条件,而原先引用这个dao的service方法不需要这个逻辑,难道直接修改这个dao方法吗?
系统开始可能觉的这样比较烦人,但是要有长远的考虑。
12 楼
jamesby
2007-02-14
xly_971223 写道
jamesby 写道
将如上代码放入DAO的超类中,这样我每一个DAO就不需要重复写这些功能雷同的代码!不知道有什么不合适之处.
无论怎么简化dao层,dao对外的接口是不变的,最终业务层还是要是调用dao层的方法,还是会出现楼主的问题
我觉得既然项目业务比较简单,省掉业务层也未尝不可, 在web层直接调用dao 。
如果遇到业务操作就写在dao层,或者web层。
我在 DAO 层所简化的也只是在DAO层把最基本的crud操作简单封装了一下,避免在所有的dao中进行crud的编写!
看来这是一个在简单和规范之间进行的选择,要简单,直接dao,要规范,加层service.
11 楼
xly_971223
2007-02-14
jamesby 写道
将如上代码放入DAO的超类中,这样我每一个DAO就不需要重复写这些功能雷同的代码!不知道有什么不合适之处.
无论怎么简化dao层,dao对外的接口是不变的,最终业务层还是要是调用dao层的方法,还是会出现楼主的问题
我觉得既然项目业务比较简单,省掉业务层也未尝不可, 在web层直接调用dao 。
如果遇到业务操作就写在dao层,或者web层。
10 楼
giscat
2007-02-14
jamesby 写道
xly_971223 写道
一种折中的办法是业务层继承dao层 业务对象要用到多个dao时会麻烦一些
像cms系统就是这种情况,大多数的操作是crud,要是按照上面的写法还不疯了
可以参考一下springside2中的方法
业务层继承DAO层,Service 肯定要访问多个DAO的,这个继承的方案有些行不通,现在已经快疯了:)
像cms系统就是这种情况,大多数的操作是crud,要是按照上面的写法还不疯了
可以参考一下springside2中的方法
giscat 写道
视情况而定,简单的合并
复杂的分分层
复杂的分分层
现在的业务基本都是这种简单的情况,因为复杂的方式要求写存储过程. 简单情况如何合并?不是很理解
简单情况直接在action里调持久层代码
如
JdbcUtil.save(objet);
JdbcUtil.update(objet);
JdbcUtil.query(sql,params);
JdbcUtil可以是对hibernate,ibatis,spring jdbctemplate,dbutil,jdbc等的封装
如果比较复杂,涉及多个实体操作,事务之类的,
再整个service出来,
9 楼
jamesby
2007-02-14
xuni 写道
写一个service和DAO的基类不就成了吗,service中有一个BaseDAO的实例,service基类的save方法调用dao的save方法,
我一直以为Service层的接口声明应该是清晰,你这样所有的save,update,delete之类的参数都是Object类型的参数了!发表评论
-
weblogic.xml文件代码示例
2008-04-19 10:44 8887<?xml version="1.0" ... -
java 运行版本问题
2008-02-26 08:33 1823在JDK 5.0 上编译好的class,即使未用到任何5.0的 ... -
sqlserver 2000 1433 端口未打开的问题
2008-02-26 08:32 2562需要安装SqlServer 2000 SP4 -
我的一次weblogic 8升级到weblogic9遇到的问题.
2007-04-29 18:17 51501、web应用的乱码问题。 原来的基于weblogic8的应用 ... -
关于手机浏览器的问题?
2007-04-20 12:07 7349现在有一个新的需求,本来目前的基于web的软件开发已经完成,但 ... -
Weblogic下的自动任务
2007-04-03 14:13 2930package com.jamesby.listener; ... -
是用SmartUpload进行文件上传
2007-04-03 14:06 5640package com.jamesby.file.servle ... -
文件下载Servlet
2007-04-03 13:57 4349package com.jamesby.action; ... -
Java 5.0 枚举
2007-03-12 15:09 2203http://www.ibm.com/developerwor ... -
关于web-inf/classes的优先级高于web-inf/lib的优先级
2007-03-08 12:11 4834背景 一直以来都知道web-inf/classes的优先级高 ... -
深入了解WebLogic的类装载机制详解
2007-03-01 19:05 2219http://publish.it168.com/2005/1 ... -
我的一次EJB重构过程
2007-03-01 12:13 2089背景 因为历史遗留问题,代码写的杂乱无章,没有条理,而且该 ... -
如何防止用户恶意的F5刷新操作的问题?
2007-02-25 18:45 13105背景: 问题是这样的,系统持久层采用ibatis架构,系统 ... -
自己实现的TransactionManager
2007-02-23 13:53 4828背景: 目前有一个系统,系统已经写好了,但是要不停的添加新的功 ... -
关于Service调用Service 的思考
2007-02-10 20:04 5173以前做软件都是随便写几个Service,纯粹为了Service ... -
通过IP访问服务器session失效,计算机名则可以,什么原因?
2007-02-08 17:26 4799最近开发一个新项目采用Spring MVC+Spring+iB ... -
Tomcat 类加载机制
2007-02-08 12:04 1756yahoo中国的一个面试题,转至水木. Tomcat Ser ... -
Weblogic 8.1.3 下数据库连接池的配置问题
2007-02-07 21:00 2596weblogic8.1.3下同一个数据库连接池最好只被一个we ... -
Weblogic 8.1.3 下如何使用JSTL
2007-02-07 20:56 3184一、下载jakarta-taglibs-standard-1. ... -
两级联动Select的TAG实现
2007-02-02 18:12 2065JSP实现太复杂而且不方便,那来个幽雅点的Tag包装! pac ...
相关推荐
Service层和DAO层是软件开发中常见的两种设计模式,主要用于分离业务逻辑和数据访问操作。在Java Web开发中,它们通常被应用于三层架构或MVC(Model-View-Controller)模型中。 DAO(Data Access Object)层是负责...
区分Action、Service和Dao功能 在软件开发中,Action、Service和Dao都是常用的架构模式,但是很多开发者对这些概念的理解和使用却存在一定的混淆。因此,本文将对Action、Service和Dao的功能进行详细的区分和解释。...
标题和描述中提到的"action层,dao层,service层,entity层"是这种分层架构的典型组成部分,下面将详细解释每一层的功能和它们之间的交互。 1. **Action层(控制层)**: 这一层主要负责接收用户的请求,进行业务...
DAO层_Service层_Controller层、View层的一些了解知识,帮助填充对这部分比较空白的开发者们。
Action、Service 和 Dao 功能解析 在不分层的系统中,我们可以将所有的代码都写到一个地方,比如 Struts 的 Action 类。在这里,我们不仅要处理页面逻辑,还要做业务逻辑,还要做数据访问。为了更好地理解和分离 ...
在Java Web开发中,"jsp、servlet进行增删改查,dao层和service层分开"是一种常见的设计模式,它遵循了MVC(Model-View-Controller)架构,旨在提高代码的可维护性和可扩展性。以下是这个模式的详细解释: 1. **...
- **Spring**:用于Service层和DAO层,提供依赖管理和事务管理等功能。 - **Hibernate**:用于DAO层,负责对象关系映射(ORM),使得Java对象能够与数据库表相对应。 3. **配置文件**:配置文件是Spring框架中的...
本文将深入探讨如何使用jsp-servlet-service-dao四层架构来实现这样的系统,包括用户信息的增删改查功能,以及权限控制机制。 首先,让我们理解这四层架构的每一层: 1. **JSP(JavaServer Pages)**:JSP是Java ...
这些工具能够根据数据库的表结构自动创建Service、Dao和Model层的代码,只需简单配置即可。 自动生成代码的步骤通常包括: 1. 配置数据库连接信息,如数据库驱动、URL、用户名和密码。 2. 指定需要生成代码的数据库...
Java代码生成器是一种工具,主要用于自动化编程过程中重复性较强的部分,比如DAO(数据访问对象)层和服务(Service)层的代码编写。DAO层是应用程序与数据库交互的主要接口,而Service层则封装了业务逻辑,两者在...
建模工具类在Dao层可能包含诸如连接管理、事务处理、SQL执行等通用功能,例如`JDBCUtils`,这是一个常用的Java JDBC辅助类,用于简化数据库连接的获取和释放,以及执行SQL语句。 `JDBCUtils`文件可能包含以下功能:...
在这个项目中,我们看到标题提到"分了dao service的ssm整合还附带分页功能",这表明项目不仅实现了SSM的基础整合,还在数据访问层(DAO)和服务层(Service)进行了分离,并且加入了分页功能,这对于新手来说是一个很好...
(2)新增Service包,创建Servicve服务类,供Servlet调用,实现业务功能; (3)对数据库的增删改查操作进行封装,提供统一的访问对象DAO类; (4)以用户注册与登陆案例的实现为例。 教学重点与难点 (1)Servlet+...
这个过程通常涉及编写DAO(Data Access Object)、Service和Controller层的代码,这些是软件架构中的核心组件。"快速生成DAO、Service、Controller等相关代码"的标题和描述暗示了一个针对这种情况的解决方案,即一个...
首先,DAO层的主要职责是处理与数据库相关的所有操作,如查询、插入、更新和删除记录。它的存在使得业务逻辑层可以专注于业务规则的处理,而无需关心底层的数据存取细节。这遵循了软件设计中的单一职责原则,提高了...
Struts2、Spring和iBatis是Java Web开发中常用的三大框架,它们分别负责MVC模式中的Action层、业务逻辑层(Service层)以及数据访问层(DAO层)。本项目提供的是一款工具,能够自动化生成这三层的代码,极大地提高了...
对于多模块的Spring Boot项目,每个模块可能包含不同的组件,如Service层、Controller层和Dao层。Dao层主要负责与数据库交互,因此它的单元测试通常涉及对数据库操作的模拟,而无需实际连接到数据库。 1. **配置多...
JUnit可以用来测试Service和DAO层的函数,而工具如Selenium可以帮助进行前端功能测试。 10. 部署与运行:项目完成后,需要打包成WAR文件部署到Web服务器,如Tomcat、Jetty等,然后通过HTTP请求访问并测试CRM系统的...
开发者可能将不同组件划分为不同的包,比如DAO层和Service层的实现可能分别放在`com.javashop.dao`和`com.javashop.service`等包下,以遵循良好的命名和组织规则。 综上所述,这个学习过程涵盖了Java开发中的关键...
在C#编程中,"通用Dao层"是一个常见的设计模式,用于封装数据库操作,使得业务逻辑层能够专注于处理业务规则,而无需关心底层数据访问的细节。本篇将重点探讨如何利用C#的特性(Attribute)标签来实现这一目标,同时...