锁定老帖子 主题:关于DAO层的疑惑!!!平地一声雷
精华帖 (0) :: 良好帖 (1) :: 新手帖 (14) :: 隐藏帖 (6)
|
|
---|---|
作者 | 正文 |
发表时间:2011-08-03
建议只有一个通用DAO,但是DAO中的查询使用面向对象,这个对象中or查询比较好解决,但是既有and 也有or 比较难办,我还没试过面向对象中,既有and又有or的情况,单单是or的试过,类似于spring管理hibernate中的findExample,只不过改写了它,用反射机制动态生成HSQ语句,service只涉及面向对象,我原来做的只是or关系;
只要对象中的属性值不空,就查询该属性; 总之,hsq是少不了的,不在service层的话,只有在DAO层动态生成,既然通用那么传过来的就是必须是对象; |
|
返回顶楼 | |
发表时间:2011-08-03
我ding通用DAO,好处很多,没必要那么教条主义。
|
|
返回顶楼 | |
发表时间:2011-08-03
1.提供基础功能方法的hibernate基类
public class HibernateGenericDao extends HibernateDaoSupport 2.使用泛型的hibernate基类. public class HibernateEntityDao<T> extends HibernateGenericDao 3.具体的业务领域类(采用注解@Repository,减少繁琐的xml配置): @Repository public class UserDaoImpl extends HibernateEntityDao<User> implements UserDao |
|
返回顶楼 | |
发表时间:2011-08-03
feiyang404 写道
最近一直在考虑一个问题,在S2SH开发中,DAO层到底应该怎么写?是一个通用DAO呢还是各个Model的DAO分开呢?
如果是各个MOdel的DAO分开写,这样会有很多重复代码,几乎每个DAO类里面都包含save,delete,update,load等一样标签的方法,和重用性相抵触,而且在application.xml中配置非常麻烦,每个DAO都得引用sessionFactory,这样配置文件也有很多冗余!
我个人认为,dao层只应提供数据持久化接口,和数据库,Service层均没有关系,如果持久化框架变了,比如不用Hibernate,而改用ibatIS,那么只需要将DAO里面的实现稍作改动,整个系统就可以流畅运行.所以,这就要求在Service层不要写HQL或者QBC,Service层专注调用DAO层接口为Action层提供服务,和DAO层无耦合.这样如果写一个通用DAO层的话,就会提高代码重用性,并且xml配置也很简洁,只要配置一个通用的dao就可以了,但是却使以牺牲灵活性为前提的,比如在Service层需要一个按属性查询的方法,那么在DAO层就要写where子句(where xxx=yyy),但是通用dao不可能知道xxx,怎么办呢?
如果通用DAO层接受Service层传来的HQL的话,那就会很容易写出一个灵活性高,重用性强的DAO通用层,但是这样又有了耦合性,持久化框架变化的话要改变的代码会很多,甚至可以说是牵一发而动全身.
所以,到底该怎么设计DAO层呢,思考良久,觉得,还是通用DAO比较合理一点,配置文件少,重用性高,这是大方向,然后如何写出一个和Service层无关的又有很高灵活性的DAO层,一直困扰我,各位大虾们,请说说你们的看法,你们有没有更好的方法?或者我的这个困惑是不是应该有的?该不该放弃低耦合?
最后,我希望大家不要用经验和我谈问题,经验都是看别人的代码学来的,真正思考过这个问题的才有发言权...
|
|
返回顶楼 | |
发表时间:2011-08-04
我写过一个通用的。你看看: http://wxinpeng.iteye.com/blog/699447
|
|
返回顶楼 | |
发表时间:2011-08-04
寫一個通用的抽象DAO沒錯,其中寫基本的CRUD就好了,其他DAO都繼承該抽象DAO,然後,各個DAO根據各自的業務需要,再添加除了從抽象DAO繼承來的method之外的method。
但是,你提出的問題:DAO層如果用ORM框架綁定了,比如service層需要傳遞相關args過來,那樣必然會耦合住。 我的意思是,如果你決定使用ORM框架了,不管你用JPA還是Hibernate或者Ibatis,DAO層跟這些關聯住了。而Service層當然也難免會有若幹method需要傳遞args,當然,args很有可能是一些hql或qbc的語法段。除非你用純sql,不然很難完全解耦合。 |
|
返回顶楼 | |
发表时间:2011-08-04
ahopedog2 写道 DAO的设计和使用与Service, Action等层次是密不可分的,因此在讨论这个问题时,我们是不是应该讨论清楚3者间的职能划分。
我见过有人这样设计和使用过: 一、Action, Service, DAO皆有,Service与DAO里的方法一一对应,大部分的逻辑处理都在DAO里面完成(许多的SQL语句),而Service则是一行调用DAO对应方法的代码。 二、觉得DAO多余,就把DAO和Service合并了(以前我就这么干过) 三、条件多点的查询,查询条件(HQL, 或SQL)从页面或Action传过来 四、Action直接调用DAO 五、一个复合的业务操作(需要由多个步骤完成),都在一个DAO中实现了 六、数据库事务放Action, Service, DAO(放哪里的都有) 总之没能合理划分3者职责的情况非常普遍,这个问题是Action, Service, DAO职能划分的问题,主要也是Service, 与DAO的职能划分。 我是这么认为的: Service的语义是业务上的,存在于Service中的方法应该是如: 创建用户账号, 增加账户余额, 用户操作违规扣除积分, 。。。 DAO中的语义则是针对数据库的,存在于其中的方法就应该说成: 创建user记录 更新account表中balance的值 更新user_score中score的值 加载user实体 加载account实体 加载user_score实体 。。。 以上的DAO方法都应是最简单的,一般都可以通过一条“简单”的SQL语句完成,如果SQL语句很复杂可能有2种情况:1)业务确实复杂,通常是查询;2)DAO方法的职责不是单一的。我们应该尽量实现单一功能的DAO方法,尽量让SQL语句简单。 Service中的内容应该是复合的,简单的CRUD那也没什么说的,想怎么就怎么吧。 逻辑稍微复杂点的功能都是可以划分成步骤的,比如对增加账户余额的功能,对应service中的方法可以是这样的 1)加载用户实体 2)用户存在,然后找到账户实体 3)验证账户余额, 4)增加或减少账户余额 上面4个方法都对应着DAO中的一个方法。 通常的业务性操作都是可以总结出这样的方法的,但也不排除一些特有操作,这个操作很不通用,就是在某一个地方使用的,根本没法复用。这可能是由于业务研究不透彻,设计不明确照成的,这很正常,因为没有足够的时间去好好推敲方法的设计吗。还有就是各种各样,五花八门的查询。 对于查询,我是没办法,干脆就一个查询一个DAO方法,参数都包含在MAP里,SERVICE里别包含SQL, HQL(HQL和SQL不都是不能垮平台、跨系统的障碍吗)。 不能闲麻烦,就是多几个配置文件吗,一个人用几天就都写完了,累是累点,但那不算是问题。真正耗费时间的是在关键代码书写上和BUG调试上。 DAO还是有存在的道理(如果只用一个通用类,那么JdbcTemplate就可以了), Service, DAO, Action3者到底应该放置什么样的代码,他们的职能划分才是关键 ,这个是正解 |
|
返回顶楼 | |
发表时间:2011-08-04
nifoo 写道 ahopedog2 写道 DAO的设计和使用与Service, Action等层次是密不可分的,因此在讨论这个问题时,我们是不是应该讨论清楚3者间的职能划分。
我见过有人这样设计和使用过: 一、Action, Service, DAO皆有,Service与DAO里的方法一一对应,大部分的逻辑处理都在DAO里面完成(许多的SQL语句),而Service则是一行调用DAO对应方法的代码。 二、觉得DAO多余,就把DAO和Service合并了(以前我就这么干过) 三、条件多点的查询,查询条件(HQL, 或SQL)从页面或Action传过来 四、Action直接调用DAO 五、一个复合的业务操作(需要由多个步骤完成),都在一个DAO中实现了 六、数据库事务放Action, Service, DAO(放哪里的都有) 总之没能合理划分3者职责的情况非常普遍,这个问题是Action, Service, DAO职能划分的问题,主要也是Service, 与DAO的职能划分。 我是这么认为的: Service的语义是业务上的,存在于Service中的方法应该是如: 创建用户账号, 增加账户余额, 用户操作违规扣除积分, 。。。 DAO中的语义则是针对数据库的,存在于其中的方法就应该说成: 创建user记录 更新account表中balance的值 更新user_score中score的值 加载user实体 加载account实体 加载user_score实体 。。。 以上的DAO方法都应是最简单的,一般都可以通过一条“简单”的SQL语句完成,如果SQL语句很复杂可能有2种情况:1)业务确实复杂,通常是查询;2)DAO方法的职责不是单一的。我们应该尽量实现单一功能的DAO方法,尽量让SQL语句简单。 Service中的内容应该是复合的,简单的CRUD那也没什么说的,想怎么就怎么吧。 逻辑稍微复杂点的功能都是可以划分成步骤的,比如对增加账户余额的功能,对应service中的方法可以是这样的 1)加载用户实体 2)用户存在,然后找到账户实体 3)验证账户余额, 4)增加或减少账户余额 上面4个方法都对应着DAO中的一个方法。 通常的业务性操作都是可以总结出这样的方法的,但也不排除一些特有操作,这个操作很不通用,就是在某一个地方使用的,根本没法复用。这可能是由于业务研究不透彻,设计不明确照成的,这很正常,因为没有足够的时间去好好推敲方法的设计吗。还有就是各种各样,五花八门的查询。 对于查询,我是没办法,干脆就一个查询一个DAO方法,参数都包含在MAP里,SERVICE里别包含SQL, HQL(HQL和SQL不都是不能垮平台、跨系统的障碍吗)。 不能闲麻烦,就是多几个配置文件吗,一个人用几天就都写完了,累是累点,但那不算是问题。真正耗费时间的是在关键代码书写上和BUG调试上。 DAO还是有存在的道理(如果只用一个通用类,那么JdbcTemplate就可以了), Service, DAO, Action3者到底应该放置什么样的代码,他们的职能划分才是关键 ,这个是正解 每個人用的架構,分的層次都不會一樣。仁者見仁,智者見智。不存在最好,只存在更好。 |
|
返回顶楼 | |
发表时间:2011-08-04
如果你用hibernate做orm框架的话,可以用一个一般dao来实现,整个dao层得功能,但这样效率不高,灵活性不强,hibernate如果涉及到表结构复杂的业务,那会是噩梦。我一直在用ibatis/mybatis框架,开始感觉确实不如hibernate只能,主要因为涉及到每个表都要有一个自己的sqlMap,这样在编码上有些费时,但是它的优点就是足够灵活,后来为了避免这个问题,把大致相同的代码抽成了一个模板,从dao-sqlmap-service-test-vo一起生成,省事又灵活。目前我感觉对于orm这块是个很不错的方法。
|
|
返回顶楼 | |
发表时间:2011-08-04
最后修改:2011-08-04
Controller --> Service --> Dao(可选) --> CommonDao
基本上的思路是 控制器、业务、数据操作独立,基本上不用接口(大家应该想想java里面接口的目的存在多个实现的时候接口才有意义) 后面各个独立的Dao他只是将业务独立出来像有洁癖的 觉的在Service里面看到Sql语句等等就很不爽 ok ! 你把那些需要的特殊的东西抽离出来 或者用命名查询 基于xml配置sql语句等等 Spring上的大致配置 Spring上利用注释配置 所以Spring上的基本配置 类似与这种 \ 如果这么点配置都觉的麻烦的话 那我也没话说 相当于只是将类注册到spring中去 <bean name="aService" class="AService"></bean> <bean name="dao" class="CommonDao"></bean> java类中引用 //controller public class Apply { @Autowired private AService aService; } //service public class AService { @Autowired private CommonDao dao; } //如果存在那种很特别dao 可以抽离出来 public class ADao { @Autowired private CommonDao dao; } <bean name="aDao" class="ADao"></bean> 大致就怎么样了 |
|
返回顶楼 | |