论坛首页 入门技术论坛

从零开始一步一步做论坛------抛砖引玉,欢迎怕转[二]

浏览 5621 次
该帖已经被评为新手帖
作者 正文
   发表时间:2011-10-04  

趁着假期,再接再厉.开发这个论坛刚开始就是数据库的设计,但是数据库的设计图在公司的电脑上,自己的电脑Rational坏了,所以数据库的设计就放到十一长假以后再说吧.

先说说我遇到的第一个大问题:dao层的设计

怎样设计一个无耦合的dao层呢?dao层设计成通用的还是各司其职的?关于这个问题我曾经在问答里提出过.连接:http://feiyang404.iteye.com/blog/1138642

虽然讨论了很久,但是没有我想要的答案,最后经过苦思冥想,我找到了自己的解决办法.

首先,我赞成通用dao层的方式,因为dao层的职责就是负责数据持久化和获取数据库数据供Service层用的,所以这个应该和Service层之间解耦合,冲着这一点,各司其职的dao层就站不住脚了.其次,通用dao层的设计,在Spring配置文件中也很好配置,只需要配置一次dao就可以在每个service中引用了.这种好处也体现在编码中,每个Service类都引用同一个dao对象,编码起来很清楚,根本不会错.

现在最大的问题就是和Service层解耦了,如果看过我上面给出的连接的话,就会明白这个问题的难度了.dao层只是负责数据持久化的,所以应该说完全要和Service层剥离,现在dao层一般采用的是HQL加Spring的HibernateTemplate来完成的,但是万一dao层不采用HQL而采用QBC怎么办?如果和Service耦合的话,这下麻烦就大了,不仅要修改dao层还要修改Service层,而且稍有不慎,连Action层都在劫难逃.我接触过的好多项目中,都有在Service层构造HQL语句然后传给dao层,这种设计虽然很方便,但是我一直很抵触,在这次开发这个论坛的之前,我发帖求助,一直没有得到想要的答案,最后没办法,自己竟然想出来了一个解决方法,呵呵,当时觉得特别高兴,但是,也仅仅是解决了问题而已,不知道这么做性能上会不会有影响.

下面我说说自己的方法,为什么我们要在Service层构造HQL语句,而不在dao层构造呢?原因之一就是Service层负责业务处理,基本的增删还好说,一旦遇到要按条件查找就不好办了,要构造where子句的key=value的形式的语句,通用dao层就不会专门有这种方法,所以也很难构造,大家都选择在Service层构造好HQL语句,直接丢给dao层执行.经过我很长时间思考,key=value的形式不正好是Map的结构吗?在Service层构造出一个条件查询的Map结构,在dao层再专门写一个函数将Map解析出来,构成HQL语句,这样,Serivce层传给dao层的也只是一个map对象,而且map对象里也包含的是普通对象,完全和dao层没有关系.下面是我的代码:

public static String createHQL(String clazz, Map mps){
		StringBuilder sb = new StringBuilder("from ").append(clazz).append(" where ");
		Iterator it = mps.keySet().iterator();
		while(it.hasNext()){
			Object o = it.next();
			sb.append(o.toString()).append("='").append(mps.get(o)).append("'").append(" and ");
		}
		System.out.println("DaoImpl.createHQL:"+sb.substring(0, sb.length()-5).toString());
		return sb.substring(0, sb.length()-5).toString();
	}

 再粘一个dao层调用的代码:

public List findByValue(String clazz, Map mps, String orderBy, String orderKey) {
		String hqlL = createHQL(clazz,mps);
		final String hql = hqlL+  " order by "+orderBy+" "+ orderKey;
		return getHibernateTemplate().executeFind(new HibernateCallback(){
			public Object doInHibernate(Session session) throws HibernateException{
				Query query = session.createQuery(hql);
				if(query.list()!=null){
					return query.list();
				}else{
					return null;
				}
			}
		});
	}

 Service调用dao的代码:

public List listForumEliteAll(long boardid){
		Map mps = new HashMap();
		mps.put("board", boardid);
		mps.put("elite", 1);
		
		List list = this.getDao().findByValue("Forum", mps, "id", Constant.DESC);
		
		return list;
	}
 

由于是Map形式的,所以可以传入任意的key=value值对,对于想按多个条件查询的情况特别管用.这种只需要在Service层构造Map结构就可以了.

有了这个办法,就可以写出完全与Service解耦合的通用dao层了.附件里是我的通用dao层,大家如果能用到,就拿去用吧!对于上述方法,希望给位多多提出宝贵意见.我也是被迫无奈,只是为了写出一个无耦合的通用dao层罢了.

原创首发,谢谢支持!

  • dao.zip (1.8 KB)
  • 下载次数: 79
   发表时间:2011-10-06  
这样只能初步解决按条件查找的情况,但是,很多时候遇到的跨表查询,还有一些排序,还有一些为NULL的查找,SQL的查询内容可以各种各样,MAP只能解决条件查找,而对于其他的关联查找,还是比较有限。


不过可以写一个整体的工具包,把所有的需求都做成MAP?再想想。。。:)
0 请登录后投票
   发表时间:2011-10-07  
一个BaseDao 一个BaseDaoImpl 做实现 其他Dao接口实现BaseDao 实现继承BaseDaoImpl
这样你的Dao才干净。。
0 请登录后投票
   发表时间:2011-10-07  
stackoverflow 写道
一个BaseDao 一个BaseDaoImpl 做实现 其他Dao接口实现BaseDao 实现继承BaseDaoImpl
这样你的Dao才干净。。

给个代码
0 请登录后投票
   发表时间:2011-10-07  
项目中有很多不一样的查询,都需要每个都写一个service,dao层,我觉得还是在service层拼接省事一些,然后直接给dao执行
0 请登录后投票
   发表时间:2011-10-07  
没有什么必要吧 建议看下 commons-dbutils

List results = (List) qr.query(conn, "select id,email,password from users", new BeanListHandler(User.class));
       
            for (int i = 0; i < results.size(); i++) {
            User gb = (User) results.get(i);
                System.out.println("id:" + gb.getId() + ",email:" + gb.getEmail());
            }
0 请登录后投票
   发表时间:2011-10-07  
这样一步一步做,什么时候才能做完啊?!有谁可以坚持下去吗?不如找几个想做自己论坛的朋友一起做,再不断修改
0 请登录后投票
   发表时间:2011-10-07  
noside 写道
这样一步一步做,什么时候才能做完啊?!有谁可以坚持下去吗?不如找几个想做自己论坛的朋友一起做,再不断修改

这几天比较忙,没有再写,上班后继续写
0 请登录后投票
   发表时间:2011-10-07  
楼主的方案说到底就是自己整一个弱类型,简化版的持久化接口。如果这个接口能提供与JPA一样的表述能力,那就是JPA的翻版,为什么不直接用JPA呢。如果不提供与JPA一样的表述能力,那就是针对具体项目的简易版,谈不上通用。

而且,ORM说我可以让你换数据库, JPA说我可以让你换ORM,LZ说我可以让你换任何持久化方案。就service到数据库这一段,业务逻辑都不在这里,建议慎重考虑一下有没有分这么多层来解耦的需要。
0 请登录后投票
   发表时间:2011-10-07   最后修改:2011-10-07
看看这个论坛

http://simpleframework.net/bbs.html
0 请登录后投票
论坛首页 入门技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics