论坛首页 入门技术论坛

DAO设计问题

浏览 5582 次
锁定老帖子 主题:DAO设计问题
该帖已经被评为新手帖
作者 正文
   发表时间:2008-08-18  
DAO
最近由于项目限制使用JDK1.4(没有办放使用泛型DAO)所以设计了一个DAO如下

public interface Dao {
	public abstract List getList(int first,int max) throws Exception;
	public abstract int getTotal()throws Exception;
}

public abstract class AbsDao extends HibernateDaoSupport implements Dao {
	
	/**
	 *@return List 以集合形式返回符合HQL语句中实体 
	 *@param int max 最大记录数
	 *@param int first 第一条记录的位置
	 */
	public List getList(final int first,final int max)throws Exception{
		
		return super.getHibernateTemplate().executeFind(
			new HibernateCallback(){
				public Object doInHibernate(Session session) throws HibernateException,SQLException{
					try{
						return session.createQuery("from "+getTableName()).setFirstResult(first).setMaxResults(max).list();
					}
					catch(Exception e){
						throw new HibernateException(e);
					}
				}
			}
		); 
	}
	
	/**
	 * @return int count 返回HQL查询的记录数
	 * @param String HQL 统计的HQL语句
	*/
	public int getTotal() throws Exception {
		return ((Integer)super.getSession().createQuery("select count(*) from "+getTableName()).uniqueResult()).intValue();
	}
	
	/**
	 * @return String TableName
	 * */
	private String getTableName()throws Exception{
		return this.getClass().getName().substring(this.getClass().getName().lastIndexOf(".")+1, this.getClass().getName().length()-3);
	}
}


///这个是工具生成的修改了继承,使得为分页作准备。
public class UserinfoDAO extends AbsDao {}


//这个是伪泛型的DAO
public class DaoImpl extends AbsDao{
	/**
	 *@return List 以集合形式返回符合HQL语句中实体 
	 *@param String HQL  要执行的HQL语句
	 */
	public List getList(String HQL)throws Exception{
		return super.getHibernateTemplate().find(HQL);
	}
	
	/**
	 *将Object写入数据库 
	 *@param Object o  要保存的对象
	 */
	public void save(Object o)throws Exception{
		super.getHibernateTemplate().save(o);
	}
	
	/**
	 *将List(Object)写入数据库 
	 *@param List list(Object)  要保存的对象数组列表
	 */
	public void saveAll(List list)throws Exception{
		super.getHibernateTemplate().save(list);
	}
	
	/**
	 *将Object更新 
	 *@param Object o  要跟新的对象
	 */
	public void update(Object o)throws Exception{
		super.getHibernateTemplate().update(o);
	}
	
	
	/**
	 *将Object更新 
	 *@param List list(Object)  要更新的对象数组列表
	 */
	public void updateAll(List list)throws Exception{
		super.getHibernateTemplate().update(list);
	}
	

	/**通过SQL语句直接操作数据库
	 * @param String HQL;
	*/
	public void excuteSQL(String HQL) throws Exception {
		super.getHibernateTemplate().find(HQL);
	}

}



服务层
public interface PageService{
	public abstract int getPageSize()throws Exception;
	public abstract void setPageSize(int pageSize)throws Exception;

	public abstract int getTotal() throws Exception;
	public abstract int getPageCount()throws Exception;
	public abstract List getFirstPage() throws Exception;
	public abstract List getLastPage() throws Exception;
	public abstract List getPreviousPage(int currentPage)throws Exception;
	public abstract List getNextPage(int currentPage)throws Exception;
	public abstract List getPointPage(int pointPage)throws Exception;

}

public abstract class AbsPageService implements PageService {
	/**
	 * @return int 数据库中记录总数
	 * */
	public int getTotal() throws Exception {
		return getDao().getTotal();
	}
	
	/**
	 *@return int totalpage 返回分页数 
	 *@param int PageSize 页面的记录数
	 */
	public int getPageCount(int PageSize) throws Exception {
		return ((getTotal()+PageSize)-1)/PageSize;
	}

	/**
	 *@return List 返回指定页面的记录  注意这个方法提供给接口方法
	 *@param int PointPage 指定的页面
	 *@param int PageSize 页面的记录数
	 */
	public List getPointPage(int PointPage, int PageSize) throws Exception {
		if(PointPage>=0&&PointPage<=getPageCount(PageSize)){
			return getDao().getList((PointPage-1)*PageSize, PageSize);
		}
		else{
			return null;
		}
	}
	
	//以下是接口方法
	/**
	 *@return List 返回第一页的记录
	 **/
	public List getFirstPage() throws Exception{
		return this.getPointPage(1, PageSize);
	}
	
	/**
	 * @return List 返回最后一页
	 * */
	public List getLastPage() throws Exception{
		return this.getPointPage(this.getPageCount(PageSize), PageSize);
	}
	
	/**
	 * @return List 返回前一页的数据
	 * @param int currentPage 当前页
	 * */
	public List getPreviousPage(int currentPage)throws Exception{
		if(currentPage>1&&this.getTotal()>currentPage){
			return this.getPointPage(currentPage-1, PageSize);
		}
		else{
			return null;
		}
	}
	
	/**
	 * @return List 返回后一页的数据
	 * @param int currentPage 当前页
	 * */
	public List getNextPage(int currentPage)throws Exception{
		if(this.getTotal()>=(currentPage+1)&&(currentPage+1)>0){
			return this.getPointPage(currentPage+1, PageSize);
		}
		else{
			return null;
		}
	}
	
	/**
	 * @return List 返回当前页的数据
	 * @param int currentPage 当前页
	 * */
	public List getPointPage(int pointPage)throws Exception{
		if(this.getTotal()>=(pointPage)&&(pointPage)>0){
			return this.getPointPage(pointPage, PageSize);
		}
		else{
			return null;
		}
	}
	
	/**
	 * @return int 总页面数
	 * */
	public int getPageCount() throws Exception {
		return this.getPageCount(this.getPageSize());
	}
	//注入方法
	public int getPageSize() {
		return PageSize;
	}

	public void setPageSize(int pageSize) {
		PageSize = pageSize;
	}
	
	public Dao getDao() {
		return dao;
	}

	public void setDao(Dao dao) {
		this.dao = dao;
	}
	
	private int PageSize=10;
	private Dao dao;
}

public interface UserinfoService {
	public abstract void regist(Userinfo ui)throws Exception;
	public abstract void delete(Integer userinfoid)throws Exception;
	public abstract void update(Userinfo ui)throws Exception;
	public abstract Map manager(String pointPage,String operator)throws Exception;
	public abstract Userinfo find(Integer userinfoid)throws Exception;
	
}

public class UserinfoServiceImpl extends AbsPageService implements PageService,UserinfoService{
	/**
	 * 用户的删除方法
	 * @param Integer userinfoid
	 * */
	public void delete(Integer userinfoid) throws Exception {
		((UserinfoDAO)super.getDao()).delete(((UserinfoDAO)super.getDao()).findById(userinfoid));
	}
	
	/**
	 * 用户的查找方法
	 * @return Userinfo
	 * @param Integer userinfoid
	 * */
	public Userinfo find(Integer userinfoid) throws Exception {
		return ((UserinfoDAO)super.getDao()).findById(userinfoid);
	}
	
	/**
	 * 用户的管理方法
	 * @param String pointPage 当前页
	 * @param String operator 操作
	 * */
	public Map manager(String pointPage,String operator) throws Exception {
		this.setAph(new PageHold());
		this.getAph().setPs(this);
		return this.getAph().getUpsPage(pointPage, operator);
	}

	/**
	 * 用户的注册方法
	 * @param Userinfo userinfo
	 * */
	public void regist(Userinfo ui) throws Exception {
		((UserinfoDAO)super.getDao()).save(ui);		
	}

	/**
	 * 用户的更新方法
	 * @param Userinfo userinfo
	 * */
	public void update(Userinfo ui) throws Exception {
		((UserinfoDAO)super.getDao()).merge(ui);		
	}
	
	public AbsPageHold getAph() {
		return aph;
	}

	public void setAph(AbsPageHold aph) {
		this.aph = aph;
	}
	
	private AbsPageHold aph;

}



工具类
public abstract class AbsPageHold {
	/**
	 * 获取页面的逻辑
	 * @return Map map
	 * @param String pointPage 当前页
	 * @param String operator 操作符 
	 * */
	public Map getUpsPage(String pointPage,String operator)throws Exception{
		Map map=null;
		try{
			if(operator==null){
				map=this.getFirstPage();
			}
			else if(operator.equals("first")){
				map=this.getFirstPage();
			}
			else if(operator.equals("previous")){
				map=this.getPreviousPage(pointPage);
			}
			else if(operator.equals("next")){
				map=this.getNextPage(pointPage);
			}
			else if(operator.equals("jump")){
				map=this.getJumpPage(pointPage);
			}
			else if(operator.equals("last")){
				map=this.getLastPage();
			}
			else{
				map=this.getFirstPage();
			}
		}
		catch(Exception e){
			System.out.println(e);
		}
		return map;
	}
	
	/**
	 * 分页所需要的帮助类
	 * */
	public Map getMap()throws Exception{
		Map map=new HashMap();
		map.put("totalCount",new Integer(this.getPs().getTotal()));
		map.put("totalPage", new Integer(this.getPs().getPageCount()));
		return map;
	}
	
	//模板方法
	public abstract Map getFirstPage()throws Exception;
	public abstract Map getLastPage()throws Exception;
	public abstract Map getNextPage(String pointPage)throws Exception;
	public abstract Map getPreviousPage(String pointPage)throws Exception;
	public abstract Map getJumpPage(String pointPage)throws Exception;
	
	//注入 
	public PageService getPs() {
		return ps;
	}
	public void setPs(PageService ps) {
		this.ps = ps;
	}
	private PageService ps;
}

public class PageHold extends AbsPageHold{
	
	public Map getFirstPage() throws Exception {
		Map map=super.getMap();
		map.put("pointPage", "1");
		map.put("list", this.getPs().getFirstPage());
		return map;
	}

	public Map getJumpPage(String pointPage) throws Exception {
		Map map=super.getMap();
		int i=Integer.parseInt(pointPage);
		List list=this.getPs().getPointPage(i);
		if(list!=null){
			map.put("pointPage", ""+(i));
			map.put("list", list);
		}
		else{
			map.put("pointPage", "1");
			map.put("list", this.getPs().getFirstPage());
		}
	
		return map;
	}

	public Map getLastPage() throws Exception {
		Map map=super.getMap();
		map.put("pointPage",((Integer)map.get("totalPage")).toString());
		map.put("list",this.getPs().getLastPage());
		return map;
	}


	public Map getNextPage(String pointPage) throws Exception {
		Map map=super.getMap();
		int i=Integer.parseInt(pointPage);
		List list=this.getPs().getNextPage(i);
		if(list!=null){
			map.put("pointPage", ""+(i+1));
			map.put("list", list);
		}
		else{
			map.put("pointPage", ""+this.getPs().getPageCount());
			map.put("list", this.getPs().getLastPage());
		}
	
		return map;
	}

	public Map getPreviousPage(String pointPage) throws Exception {
		Map map=super.getMap();
		int i=Integer.parseInt(pointPage);
		List list=this.getPs().getPreviousPage(i);
		if(list!=null){
			map.put("pointPage", ""+(i-1));
			map.put("list", list);
		}
		else{
			map.put("pointPage", "1");
			map.put("list",this.getPs().getFirstPage());	
		}
		return map;
	}

}
。


现在问题是。我没有办法写一个通用的DAO接口实现CURD。
用伪泛型DAO无法解决注入问题。还有伪泛型DAO怎么处理SQL语句?放在Service层么?
似乎不怎么合适。
还有就是分页的时候PAGEHOLD(分页)和Userinfo相互交叉。
DTO传输应该放在什么地方?
等诸如此类的问题。请指点一下。
   发表时间:2008-08-18  
把 DAO 和 Service 合并更符合 Don't repeat your self. 的原则。
0 请登录后投票
   发表时间:2008-08-18  
citysir 写道
把 DAO 和 Service 合并更符合 Don't repeat your self. 的原则。

能否解释下?不很明白。
0 请登录后投票
   发表时间:2008-08-19  
无非多传一个参数  Table...
0 请登录后投票
   发表时间:2008-08-19  
laiseeme 写道
无非多传一个参数  Table...


真的合适吗?我不很明白你意思,多传Table ?


最重要的   
不会每个表都建立一个接口继承DAO 接口 
然后再写DAOimpl  最后用模式管理?

还有就是 ServiceImpl里面 根PageHold 交叉。是否意味着
设计不当?
0 请登录后投票
   发表时间:2008-08-19  
建议在dao层 不要写死sql 除非是经常用到的sql 例如 from Table ,实现 Don't repeat
servive层才是你要书写sql 的合理地方,因为service是业务层 ,因为业务是不断变化的,而dao仅仅实现一个与数据库交互的一个接口
0 请登录后投票
   发表时间:2008-08-20  
litianyi520 写道
建议在dao层 不要写死sql 除非是经常用到的sql 例如 from Table ,实现 Don't repeat
servive层才是你要书写sql 的合理地方,因为service是业务层 ,因为业务是不断变化的,而dao仅仅实现一个与数据库交互的一个接口


我理解你意思了,可是如果 这么做的话会造成Hibernate入侵Service。不便于解耦,
我曾考虑利用面向接口的思想 把SQL注入到一个DAO的辅助类,该类有个MAP 储存各种SQL。运行时根据注入来调整SQL。不过造成的问题是。一个DAO要有个辅助的类,过于臃肿。SQL数量多的话不便于管理。

如果按照Service层持有SQL的话,只需要一个DAO,矛盾主要集中在SQL语句上。
0 请登录后投票
   发表时间:2008-08-20  
结构如下
public interface Dao {
	public List getList(String HQL) throws Exception;
	public List getList(String TableName,int first,int max) throws Exception;
	public void saveupdate(String HQL) throws Exception;
	public void save(Object o) throws Exception;
	public void saveAll(List list) throws Exception;
	public void update(Object o) throws Exception;
	public void updateAll(List list) throws Exception;
	public int getTotal(String HQL)throws Exception;
}

public abstract class AbsDao implements Dao {

	/**
	 *@return Object 以Object形式返回符合HQL语句的实体 
	 *@param Class K 要查找的类
	 *@param Integer id 查找的实体ID
	 */
	public Object getObject(Class k,Integer id)throws Exception{
		Session session=null;
		Transaction tx=null;
		Object o;
		try{
			session=HibernateSessionFactory.getSession();
			tx=session.beginTransaction();
			o=session.get(k,id);
			tx.commit();
		}
		catch(Exception ex){
			if(tx!=null){
				tx.rollback();
				tx=null;
			}
		
			throw new Exception("出错了 "+ex);  
		}
		finally{
			try{
				if(session!=null){
					session.close(); 
				}
			}
			catch(Exception e){
				System.out.println("出错了e "+e);
			}
		}
		return o;
	}

}

public class DaoImpl extends AbsDao implements Dao {
	/**
	 *@return List 以集合形式返回符合HQL语句中实体 
	 *@param String HQL  要执行的HQL语句
	 */
	public List getList(String HQL)throws Exception{
		Session session=null;
		Transaction tx=null;
		List list;
		try{
			session=HibernateSessionFactory.getSession();
			tx=session.beginTransaction();
			list=session.createQuery(HQL).list();
			tx.commit();
		}
		catch(Exception ex){
			if(tx!=null){
				tx.rollback();
				tx=null;
			}
		
			throw new Exception("出错了 "+ex);  
		}
		finally{
			try{
				if(session!=null){
					session.close(); 
				}
			}
			catch(Exception e){
				System.out.println("出错了e "+e);
			}
		}
		return list;
	}
	
	/**
	 *将Object写入数据库 
	 *@param Object o  要保存的对象
	 */
	public void save(Object o)throws Exception{
		Session session=null;
		Transaction tx=null;
		List list;
		try{
			session=HibernateSessionFactory.getSession();
			tx=session.beginTransaction();
			session.save(o);
			tx.commit();
		}
		catch(Exception ex){
			if(tx!=null){
				tx.rollback();
				tx=null;
			}
		
			throw new Exception("出错了 "+ex);  
		}
		finally{
			try{
				if(session!=null){
					session.close(); 
				}
			}
			catch(Exception e){
				System.out.println("出错了e "+e);
			}
		}
	}
	
	/**
	 *将List(Object)写入数据库 
	 *@param List list(Object)  要保存的对象数组列表
	 */
	public void saveAll(List list)throws Exception{
		Session session=null;
		Transaction tx=null;
		try{
			session=HibernateSessionFactory.getSession();
			tx=session.beginTransaction();
			Iterator it=list.iterator();
			while(it.hasNext()){
				session.save(it.next());	
			}
			session.flush();
			session.clear();
			tx.commit();
		}
		catch(Exception ex){
			if(tx!=null){
				tx.rollback();
				tx=null;
			}
		
			throw new Exception("出错了 "+ex);  
		}
		finally{
			try{
				if(session!=null){
					session.close(); 
				}
			}
			catch(Exception e){
				System.out.println("出错了e "+e);
			}
		}
	}
	
	/**
	 *将Object更新 
	 *@param Object o  要跟新的对象
	 */
	public void update(Object o)throws Exception{
		Session session=null;
		Transaction tx=null;
		List list;
		try{
			session=HibernateSessionFactory.getSession();
			tx=session.beginTransaction();
			session.update(o);
			tx.commit();
		}
		catch(Exception ex){
			if(tx!=null){
				tx.rollback();
				tx=null;
			}
		
			throw new Exception("出错了 "+ex);  
		}
		finally{
			try{
				if(session!=null){
					session.close(); 
				}
			}
			catch(Exception e){
				System.out.println("出错了e "+e);
			}
		}
	}
	
	
	/**
	 *将Object更新 
	 *@param List list(Object)  要更新的对象数组列表
	 */
	public void updateAll(List list)throws Exception{
		Session session=null;
		Transaction tx=null;
		try{
			session=HibernateSessionFactory.getSession();
			tx=session.beginTransaction();
			Iterator it=list.iterator();
			while(it.hasNext()){
				session.update(it.next());	
			}
			session.flush();
			session.clear();
			tx.commit();
		}
		catch(Exception ex){
			if(tx!=null){
				tx.rollback();
				tx=null;
			}
		
			throw new Exception("出错了 "+ex);  
		}
		finally{
			try{
				if(session!=null){
					session.close(); 
				}
			}
			catch(Exception e){
				System.out.println("出错了e "+e);
			}
		}
	}
	
	/**
	 *@return List 以集合形式返回符合HQL语句中实体 
	 *@param String HQL  要执行的HQL语句
	 *@param int first 第一条记录的位置
	 */
	public List getList(String HQL,int first,int max)throws Exception{
		Session session=null;
		Transaction tx=null;
		List list;
		try{
			session=HibernateSessionFactory.getSession();
			tx=session.beginTransaction();
			list=session.createQuery(HQL).setFirstResult(first).setMaxResults(max).list();
			tx.commit();
		}
		catch(Exception ex){
			if(tx!=null){
				tx.rollback();
				tx=null;
			}
		
			throw new Exception("出错了 "+ex);  
		}
		finally{
			try{
				if(session!=null){
					session.close(); 
				}
			}
			catch(Exception e){
				System.out.println("出错了e "+e);
			}
		}
		return list;
	}

	/**
	 *@return int 返回统计符合SQL语句的条数 
	 *@param String HQL 执行的统计语句
	 */
	public int getCount(String HQL)throws Exception{
		Session session=null;
		Transaction tx=null;
		Integer i=new Integer(0);
		try{
			session=HibernateSessionFactory.getSession();
			tx=session.beginTransaction();
			i=(Integer)session.createQuery(HQL).uniqueResult();
			tx.commit();
		}
		catch(Exception ex){
			if(tx!=null){
				tx.rollback();
				tx=null;
			}
			throw new Exception("出错了 "+ex);  
		}
		finally{
			try{
				if(session!=null){
					session.close(); 
				}
			}
			catch(Exception e){
				System.out.println("出错了e "+e);
			}
		}
		return i.intValue();
	}
	/**通过SQL语句直接操作数据库
	 * @param String HQL;
	 * */
	public void saveupdate(String HQL) throws Exception {
		Session session=null;
		Transaction tx=null;
		try{
			session=HibernateSessionFactory.getSession();
			tx=session.beginTransaction();
			session.createQuery(HQL);
			tx.commit();
		}
		catch(Exception ex){
			if(tx!=null){
				tx.rollback();
				tx=null;
			}
		
			throw new Exception("出错了 "+ex);  
		}
		finally{
			try{
				if(session!=null){
					session.close(); 
				}
			}
			catch(Exception e){
				System.out.println("出错了e "+e);
			}
		}
	}
	
	/**
	 * @return int count 返回HQL查询的记录数
	 * @param String HQL 统计的HQL语句
	 * */
	public int getTotal(String HQL)throws Exception{
		Session session=null;
		Transaction tx=null;
		int i;
		try{
			session=HibernateSessionFactory.getSession();
			tx=session.beginTransaction();
			i=((Integer)session.createQuery(HQL).uniqueResult()).intValue();
			tx.commit();
		}
		catch(Exception ex){
			if(tx!=null){
				tx.rollback();
				tx=null;
			}
			throw new Exception("出错了 "+ex);  
		}
		finally{
			try{
				if(session!=null){
					session.close(); 
				}
			}
			catch(Exception e){
				System.out.println("出错了e "+e);
			}
		}
		return i;
	}
}



然后利用注入如(Spring)管理SQL?
一个Service持有多个SQL时候SQL混乱~
似乎感觉还不如封装的方便。

当然多表多条件的情况除外。
我是不是走入误区了?
0 请登录后投票
   发表时间:2008-08-31  
提个建议,分页器那段,分页器里多个法在多次调用getTotal()方法,而getTotal()需要读取数据库,建议加个属性保存下total的值,就不用多次读数据库。
0 请登录后投票
   发表时间:2008-08-31  
ll.jpg
  • 描述: ll.jpg
  • 大小: 2.4 KB
0 请登录后投票
论坛首页 入门技术版

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