`
anson_xu
  • 浏览: 513219 次
  • 性别: Icon_minigender_1
  • 来自: 惠州
社区版块
存档分类

我的通用DAO理解,请大家指正

    博客分类:
  • SSH
阅读更多
首先声明我的资料大我来自javaeye,先谢谢各位.
但因本人理解能力不足,现把我对通用DAO的引用贴出,望大家指点.
1.BaseDAO 接口
public interface BaseDAO<T, ID extends Serializable> {
public void save(T entity);
public void delete(T entity);
public T findById(Class<T> entityClass, ID id);
}
2.BaseDAO 的实现
public class BaseHibernateDAO<T, ID extends Serializable> extends HibernateDaoSupport implements BaseDAO<T,ID> {  
      private static final Logger logger = Logger.getLogger(BaseHibernateDAO.class);  
    public void save(T entity) {          
        try {  
            getHibernateTemplate().save(entity);  
        } catch (RuntimeException e) {  
            logger.error("保存实体异常", e);  
            throw e;  
        }  
    }  

    public void delete(T entity) {  
        try {  
            getHibernateTemplate().delete(entity);  
        } catch (RuntimeException e) {  
            logger.error("删除实体异常", e);  
            throw e;  
        }  
    }  

    public void saveOrUpdate(T entity) {  
        try {  
            getHibernateTemplate().saveOrUpdate(entity);  
        } catch (RuntimeException e) {  
            logger.error("更新或保存实体异常", e);  
            throw e;  
        }  
    }  

    @SuppressWarnings("unchecked")  
    public T findById(Class<T> entityClass, ID id) {  
        try {  
            return (T) getHibernateTemplate().get(entityClass, id);  
        } catch (RuntimeException e) {  
            logger.error("查找指定ID实体异常,ID:" + id, e);  
            throw e;  
        }  
    }  
3.一个实体DAO接口extends BaseDAO
public interface ProductDAO extends BaseDAO<Product,Integer>{
//如添加
public void productInsert(Product entity);
         public void findById(Product entityClass, Integer id)
        //如除crud外Product自己的业务的方法
          public void myProductDelete(class clz,Serializable pk);
......
}
4.实体DAO的实现
public class ProductDAOImpl extends BaseHibernateDAO<Product,Integer> implements
ProductDAO {
       public void productInsert(Product entity) {
save(entity);
       }
    public void findById(Class<T> entityClass, ID id) {
findById(entityClass,id);
       }
        public void myProductDelete(class clz,Serializable pk){
           Object object = this.getHibernateTemplate().get(clazz, pk);
this.getHibernateTemplate().delete(object);     
}
  ........
}
5.service层 实体接口
public interface ProductService {
// 添加
public void productInsert(Product entity) throws ProductException;
         public void save(Product  entity) throws ProductException;
public void delete(Product  entity) throws ProductException;
public Product findById(Product entityClass, Integer) throws ProductException;
}
6.service层 实体service实现
public class ProductServiceImpl implements ProductService {
private ProductDAO productDAOImpl;

public void delete(int id) throws ProductException {
try{
productDAOImpl.Delete(productDAOImpl.findproductByPrimaryKey(id));
}catch(Exception e ){
e.printStackTrace();
throw new ProductException(this.getClass().getName()+"Product Delete 删除失败");
}
}

public void save(Product product) throws ProductException {
try{
productDAOImpl.save(product);
}catch(Exception e){
e.printStackTrace();
throw new ProductException(this.getClass().getName()+"Product Insert 添加失败");
}
.......
}


请大家帮我看看我这个通用baseDAO的设计是否合理?
具体如:
1.dao的设计有没错?
2.T Class<T>等泛型,反射有没错?
3.service层的传值有没错?
4.这样的异常处理合理吗?
5.就这样的写法是否存在不合理的的写法,而我又不知道的?

     各位拍砖吧,至少知道那里不足,继续学习..........


分享到:
评论
47 楼 fenghen 2008-11-25  
一直往上抛。。。当然不能抛给用户。。。自定义异常截获
46 楼 icewubin 2008-11-25  
helloxuweifu@hotmail.com 写道
楼上的考虑得很周到,你说的我重点是说第二种业务异常,很有道理,可我还是想你对我现在贴出来的代码及上面提到的问题进行针对性回答.

假设自定义的非受控异常名字叫TestException
try{ 
  xxxServiceImpl.insert(product); 
[b][color=red]}catch(TestException ex ){
  throw new ChipInException(ex.getMessage());[/color][/b]
}catch(Exception e ){ 
  e.printStackTrace(); 
  throw new ChipInException("保存失败"); 
}


只要这样就行了,当然这是为了和你目前的风格相符做出的改动。
catch的异常来自于serviceImpl,也可以来自于Dao中抛出的TestException,
ex.getMessage()具体内容和组织你可以自由发挥。

至于你说的“上面提到的问题”,不是很清楚指的是什么,很多人说了很多问题,你是指哪几个问题?

通用拦截器只是个建议,没有现成代码供你参考,建议是等需求比较清楚了再考虑。
45 楼 llying 2008-11-25  
wcleye 写道
zhu_chen001 写道
dao最好不要显示的抛出任何的异常
service最好抛出自定义异常


我的做法好像和你相反,在DAO层抛出自定义异常,在Action中捕捉异常做流程跳转处理..

我也认为这样做最好,
不过建议全部异常由同一的异常框架处理

44 楼 anson_xu 2008-11-24  
楼上的考虑得很周到,你说的我重点是说第二种业务异常,很有道理,可我还是想你对我现在贴出来的代码及上面提到的问题进行针对性回答.
43 楼 icewubin 2008-11-23  
引用没错,楼主一看就知道,他那篇太长了,我怕引用了污染版面。
42 楼 侯风玄黄 2008-11-23  
引用出错。
41 楼 icewubin 2008-11-23  
showtime520 写道
SQL异常等无法处理直接抛出由struts的异常处理架构处理,service层最好不抛出异常,而是返回一些有意义的标识。实在无法返回采用异常。异常很耗资源,尽量少抛出自定义异常。

异常消耗资源在JDK1.4以后可以忽略不计,老黄历了。自定义(且非受控)异常作为消息传递机制是非常好的方法,有何不可。

难道要用C时代的设置不同的返回错误代码(并且维护一张错误代码表)?或是特别定义一个返回类型(丧失返回类型的特殊性并进一步丧失编译器检查的好处)?
40 楼 icewubin 2008-11-23  
helloxuweifu@hotmail.com 写道
期待回复中......


不对,可能我没说清楚,异常分为两种。

1.第一种是系统异常,一般在action中处理,你说的场景“保存失败”就算是这一种(可能是数据库服务器down机导致),但是这一类最好能够提炼出通用需求,用过滤器或者拦截器一次性搞定。

2.我重点是说第二种业务异常,例用户注册的时候,假设有两种失败的可能,用户名已存在或身份证号已存在,此时就是两种完全不同的两种返回结果,你打算如何实现。个人认为最佳的策略就是用自定义(且非受控)的异常来进行消息传递,当然也是在action中处理,但是是拦截自定义异常的方式。
39 楼 H_eaven 2008-11-23  
kaki 写道
尽量不要用泛型,现在生产环境大多都是jdk412的版本哦。


Java范型相比C++范型没那么强大,但如果能带来好处仍然要使用的,至少相比数组,数组已越来越没优势.
企业应用也终会过度到1.5,1.6,1.X,...;
讨论贴嘛,总会比实际应用左一些.
38 楼 anson_xu 2008-11-22  
actionMessages的使用呢?
37 楼 kaki 2008-11-22  
尽量不要用泛型,现在生产环境大多都是jdk412的版本哦。
36 楼 H_eaven 2008-11-22  
showtime520 写道
SQL异常等无法处理直接抛出由struts的异常处理架构处理,service层最好不抛出异常,而是返回一些有意义的标识。实在无法返回采用异常。异常很耗资源,尽量少抛出自定义异常。


是利用异常还是返回标识,这个存在一个折中.
不过很少情况下因为异常成为程序的性能瓶颈原因,异常是语言级别的错误处理机制,返回值的方式是语言之外的.
C没有异常处理,返回值当然是解决办法,Java并不和C一样,有更好的错误处理方式.
如果异常真得成为程序的性能瓶颈原因,那就用返回值吧,不过一定要做好文档说明.这也是返回值不太好的地方,异常一般都是自描述.
能够升级一下硬件的话可能更有效吧.
35 楼 showtime520 2008-11-22  
SQL异常等无法处理直接抛出由struts的异常处理架构处理,service层最好不抛出异常,而是返回一些有意义的标识。实在无法返回采用异常。异常很耗资源,尽量少抛出自定义异常。
34 楼 jhaij 2008-11-22  
package net.vschool.util.dao;

/**
 *  该类为hibernaeDao的基础类,所以其它模块的类的dao都集成该接口
 *  @author cheafen
 *  @version 1.0 05/30/2007
 *  @since 1.0
 */
import java.io.Serializable;
import java.util.Collection;

public interface GenericDao<T,ID extends Serializable> {
	/**
	 * 根据对象id获得一个对象
	 * @param id 对象主键id
	 * @return 返回一个对象类型
	 */
	T loadObjectById(ID id);	
	
	/**
	 * 保存一条新的记录或者跟新一条新的记录
	 * @param entity 一个对象实体
	 * @return 返回保存的对象实体
	 */
	T saveOrUpdate(T entity);
	
	/**
	 * 删除一个对象实体
	 * @param entity 对象实体
	 */
	void delete(T entity);
	
	/**
	 * 查询出所有的对象集合
	 * @return 返回一个对象实体的集合
	 */
	Collection<T> findAll();
	
	/**
	 * 根据条件列出对象实体集合
	 * @param cmd HQL语句的查询相关关键字
	 * @param params 参数数组
	 * @param page 显示的第几个页面
	 * @param count 一共返回的条数
	 * @return 返回集合为count+1条记录的集合
	 */
	Collection findCmd(String cmd,Object[] params,int page,int count);
	
	/**
	 * 根据动态queryHql来列出对象实体集合
	 * @param querySql 查询语句
	 * @param page 显示的第几页面
	 * @param count 集合的条数
	 * @return 返回集合为count+1条记录的集合
	 */
	Collection<Object>findCmdByDyn(String querySql,int page,int count);
	
	/**
	 * 根据cmd对应语句查询可以执行如下操作:count、max、min、sum、avg
	 * count: select count(*) from net.vschool.user.User as user 
	 * max: select max(user.id) from net.vschool.user.User as user
	 * min: select min(user.id) from net.vschool.user.User as user
	 * sum: select sum(user.id) from net.vschool.user.User as user
	 * avg: select avg(user.id) from net.vschool.user.User as user
	 * @param cmd HQL语句的查询相关关键字
	 * @return 对应字段最大值
	 */
	Object queryByCmd(String cmd,Object[] params);
}


实现:

/**
 * 
 */
package net.vschool.util.dao.hibernate;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.Collection;
import java.util.List;

import net.vschool.util.dao.GenericDao;
import net.vschool.util.dao.ObjectParser;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;


/**
 * @author lovejj
 * 
 */
public class HibernateBaseDaoImpl<T,ID extends Serializable> extends HibernateDaoSupport implements GenericDao<T,ID> {
	private Class<T> persistentClass=null;
	/*
	 * Cmd parameter is the named query's name. Please refer to Hibernate Named Query.
	 * 
	 * @see com.zybedu.dao.FindCmdDao#findCmd(java.lang.String,
	 *      java.lang.Object[], int, int)
	 */
	@SuppressWarnings("unchecked")
	public Collection findCmd(final String cmd, final Object[] params,
			final int page, final int count) {
		List result = null;
		Object o = this.getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session)
					throws HibernateException {
				Query query = session.getNamedQuery(cmd);
				if (params != null) {
					int len = params.length;
					for (int i = 0; i < len; i++) {
						query.setParameter(i, params[i]);
					}
				}
				if (page > 0) {
					int maxResult = count;
					if (count < 1)
						maxResult = 1;
					int first = (page - 1) * maxResult;
					query.setFirstResult(first);
					query.setMaxResults(maxResult + 1);
				} else {

				}
				List list = query.list();
				org.hibernate.Hibernate.initialize(list);
				return list;
			}
		});
		if (o != null)
			result = (List) o;
		return result;
	}

	public void delete(T entity) {
		this.getHibernateTemplate().delete(entity);
		this.getSession().flush();
	}

	@SuppressWarnings("unchecked")
	public List<T> findAll() {
		List list= this.getHibernateTemplate().loadAll(this.getPersistentClass());
		org.hibernate.Hibernate.initialize(list);
		return list;
	}


	@SuppressWarnings("unchecked")
	public T loadObjectById(ID id) {
		return (T)this.getHibernateTemplate().get(this.getPersistentClass(), id);
	}

	public T saveOrUpdate(T entity) {
		this.getHibernateTemplate().saveOrUpdate(entity);
		return entity;
	}

	protected Class<T> getPersistentClass(){
		if(this.persistentClass==null){
		this.persistentClass = (Class<T>) ((ParameterizedType) getClass()
				.getGenericSuperclass()).getActualTypeArguments()[0];
		}
		return this.persistentClass;
	}

	public Collection<Object> findCmdByDyn(String querySql, final int page, final int count) {
		List result=null;
		final String fullHql=querySql;
		//LazyParser parser=parsers.get(cmd);
		if(fullHql!=null)
		{
			Object o=this.getHibernateTemplate().execute
			(
					new HibernateCallback() 
					{
						public Object doInHibernate(Session session) throws HibernateException 
						{

							Query query=session.createQuery(fullHql);
							
							if(page>0){
								int maxResult =count;
								if(count<1) maxResult=1;
								int first=(page-1)*maxResult;
								query.setFirstResult(first);
								query.setMaxResults(maxResult+1);
							}
							
							List list=query.list();												
							return list;
						}
					});
			if(o!=null) result=(List)o;
		}
		return result;
	}

	public Object queryByCmd(final String cmd,final Object[] params) {
		// 
		Object avg = null;
		Object avgTemp = this.getHibernateTemplate().execute(new HibernateCallback() {
			public Object doInHibernate(Session session)
					throws HibernateException {
				Query query =  session.getNamedQuery(cmd);
				
				if (params != null) {
					int len = params.length;
					for (int i = 0; i < len; i++) {
						query.setParameter(i, params[i]);
					}
				}
				return query.uniqueResult();
			}
		});
		if (avgTemp != null)
			avg =  avgTemp;
		return avg;
	}


}
33 楼 yuxianghong 2008-11-22  
这样的结构看见过。和前面的看法一样,不在DAO中处理异常,而是在service中抛出自定义的异常。
32 楼 anson_xu 2008-11-22  
期待回复中......
31 楼 anson_xu 2008-11-22  
前面的朋友提到异常UI的交互,
下面我又接着写了action异常处理,大家看看是否合理
请先看配置:
1.struts-config.xml配置
<global-exceptions>
   <exception key="error" type="com.kkk.exceptions.ChipInException" path="/commons/messages.jsp"/>
</global-exceptions>
2.action中的代码
public ActionForward saveChip(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {

if(ename==null||ename.equals("")){
messages.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("ename.null"));
saveMessages(request, messages);
    throw new ChipInException("名字为空");
}
try{
  xxxServiceImpl.insert(product);
}catch(Exception e ){
  e.printStackTrace();
  throw new ChipInException("保存失败");
}

}
3.资源文件中的配置
error=some errors here
ename.null=please select one name first!!!  
4.显示异常页面
<%-- Error Messages --%>
<logic:messagesPresent>
<div class="error">
<html:messages id="error">
${error}<br/>
</html:messages>
</div>
</logic:messagesPresent>

<%-- Success Messages --%>
<logic:messagesPresent message="true">
<div class="message" id="message">
<html:messages id="message" message="true">
${message}<br/>
</html:messages>
</div>

<script type="text/javascript">

new Effect.Highlight('message');
window.setTimeout("Effect.DropOut('message')", 1000);

</script>
</logic:messagesPresent>


我的问题是

我这里的异常处理及转向合理吗?配置文件的配置有没错?
key="error"是不是说明会读取资源文件中的error的值到messages.jsp页面显示?
还是说显示我action中的messages存的ename.null的资源文件值信息?
其实具体应该如何来进行这个异常处理在这几个文件中的配置?这里的异常显示页面message.jsp会不会和<global forwards>的有重合?
我要让"名字为空"这几个字在message.jsp页面中显示有办法吗?

Effect未定义是不是少了包支持?
30 楼 H_eaven 2008-11-22  
amonlei 写道
通用dao??先明确通用的范围,是基于sql的通用呢?还是基于所有orm技术的通用呢?



这个通用的角度找得好啊.
我看J2EE without EJB中 Rod 对DAO的设计的问题,就应该是基于sql关系手动处理对象关系映射,还是基于orm自动对象关系映射,就算都是orm,但JDO,TopLink,Hibernate之间的行为也不同(详细的就看without EJB吧).因为一不小心就会写出不可移植得DAO,也就无所谓通用了.不过Rod也说了就算写出这样的通用DAO,意义也并不大,持久策略(sql或orm只是实现之一)一般在设计前期都定好了,这个应该和实现可移植性的问题差不多吧,只是这种通用DAO本身是设计策略并不是实现策略,问题有点儿不明显吧.

当然LZ写得通用角度也很好,利用范形定义出所有DAO的最基本操作(CURD),还是可以少写些代码的.

异常应该有自己的业务层异常体系,在Service捕获感兴趣的DAO层的UnChecked异常并转译成自定义的业务异常.
29 楼 icewubin 2008-11-21  
mikehuhu 写道
classicbride 写道
呵呵.. 昨天偶也写了一个 和你的差不多,不过没有捕获异常。。。我认为没有必要捕获异常,用spring捕一下就o了..


spring倾向于所有的异常都不处理,认为处理也无用,但实际有部分是可以有合理提示的~~

有合理提示也是属于UI交互领域的,不应在Dao里处理。
28 楼 mikehuhu 2008-11-21  
classicbride 写道
呵呵.. 昨天偶也写了一个 和你的差不多,不过没有捕获异常。。。我认为没有必要捕获异常,用spring捕一下就o了..


spring倾向于所有的异常都不处理,认为处理也无用,但实际有部分是可以有合理提示的~~

相关推荐

    我的通用DAO理解.rar

    在这个"我的通用DAO理解"的资源中,我们可以看到作者提供了一个封装了数据库操作的DAO实现,这通常包括增删查改等基本功能,对于Java开发者来说,这是一个非常实用的工具或学习案例。 首先,让我们详细了解一下DAO...

    泛型通用DAO,可以很简化DAO层的代码

    在Java编程领域,DAO(Data Access Object)模式是一种常见的设计模式,用于封装对数据库的操作,以...然而,理解其背后的原理和限制,以及何时选择使用或避免使用泛型通用DAO,是每个专业Java开发者应该掌握的知识点。

    java 基于泛型与反射的通用 DAO

    本文将深入探讨如何结合这两种技术实现一个通用的DAO(Data Access Object)设计模式。 首先,我们来看“泛型”。泛型是Java 5引入的新特性,它允许在类、接口和方法中使用类型参数,从而提高了代码的类型安全性和...

    hibernate4 通用dao,service

    由于没有具体的文件列表,我们无法详细讨论每个文件的内容,但根据标题和描述,我们可以推断这是一个关于使用Hibernate4创建通用DAO和Service的教程或资源,旨在帮助Java开发者理解和应用这种模式来提高开发效率。...

    java ssh通用DAO另类实现示例

    首先,理解SSH框架中的DAO设计模式至关重要。DAO是一种设计模式,它为应用程序提供了一种抽象的接口,以便与数据库进行交互,同时避免了硬编码SQL语句和紧密耦合数据库细节的问题。在SSH框架中,Hibernate作为ORM...

    Hibernate通用Dao设计。

    本篇文章将深入探讨Hibernate的通用Dao设计,帮助开发者理解如何利用Hibernate提高代码复用性和可维护性。 在传统的Java应用程序中,DAO(Data Access Object)层是用于封装数据库访问逻辑的地方,它隔离了业务逻辑...

    高仿JPA自定义通用DAO

    自定义通用DAO实现基本的CRUD,比如: public interface BaseDao&lt;T&gt; { int insert(T obj) throws Exception; int update(T obj) throws Exception; int deleteByPrimaryKey(Object key) throws Exception; int ...

    C#特性标签实现通用Dao层

    在C#编程中,"通用Dao层"是一个常见的设计模式,用于封装数据库操作,使得业务逻辑层能够专注于处理业务规则,而无需关心底层数据访问的细节。本篇将重点探讨如何利用C#的特性(Attribute)标签来实现这一目标,同时...

    Hibernate_通用DAO模式,一个写好的dao层

    本资源“Hibernate_通用DAO模式”提供了一种适用于不同类型表单的DAO实现,基于SSH(Struts2、Spring、Hibernate)框架,特别强调简洁、易懂和高可移植性。 首先,SSH框架是Java Web开发中的经典组合,Struts2负责...

    JDBCTemplate+JavaPOJO实现通用DAO

    在这个"JDBCTemplate+JavaPOJO实现通用DAO"的项目中,我们将探讨如何利用这两者构建一个通用的DAO层。 首先,Java POJO(Plain Old Java Object)是指那些没有特殊约束的简单Java对象,通常用于表示数据库中的实体...

    通用DAO

    这些示例可以帮助我们更好地理解和应用通用DAO。 总结来说,通用DAO是Java开发中提高效率的有效工具,通过反射机制实现了对多种数据库实体的通用操作,降低了代码的冗余。理解和掌握这一技术,对于提升Java开发人员...

    Hibernate 原生通用DAO

    **Hibernate原生通用DAO**是基于Hibernate框架设计的一种简化数据访问操作的方式,它模仿了Spring框架中的`HibernateTemplate`类,旨在提供一个简单易用的DAO(Data Access Object)层,方便开发人员进行数据库操作...

    Hibernate通用Dao

    通用dao,简单全面,所有dao都可以继承这个dao.

    ssm(Spring-springMVC-Mybatis)通用Dao框架

    SSM(Spring-SpringMVC-Mybatis)通用Dao框架是一个常见的Java Web开发架构,它整合了Spring、SpringMVC和Mybatis三个强大的开源框架,为开发者提供了便捷的数据访问和业务逻辑处理能力。这个框架的使用可以显著提高...

    Hibernate的通用dao

    **标题:“Hibernate的通用DAO”** 在Java编程领域,Hibernate是一个强大的对象关系映射(ORM)框架,它允许开发者以面向对象的方式处理数据库操作,从而减少了对SQL的直接依赖。通用DAO(Data Access Object)是一...

    SSH中通用dao类

    在这个场景中,"SSH中通用DAO类"指的是在SSH框架下设计和实现的可以应用于多种业务场景的数据访问对象(Data Access Object)类。 DAO层是三层架构或MVC架构中的一个重要部分,主要负责与数据库进行交互,将业务...

    JdbcTemplate通用泛型Dao实现

    本文将深入探讨`JdbcTemplate`通用泛型Dao实现的相关知识点,帮助开发者更好地理解和应用这一技术。 首先,让我们了解什么是`JdbcTemplate`。它是Spring框架的一部分,用于处理SQL操作。`JdbcTemplate`提供了一组...

    Java源代码一个简单的通用DAO实现(基于hibernate)

    Java源代码 一个简单的通用DAO实现 (基于hibernate)面向应用层按POJO类缓存hibernate的session对象.使用举例: DAO dao = DAOFactory.getDAO(POJO.class);//获得一个全局类单例的DAO实例 dao.save(pojo); 你也可以...

    mybatis 通用DAO 简单实现

    MyBatis 通用DAO(Data Access Object)是一种设计模式,旨在提供一种标准的方式来访问数据库,减少重复代码,提高开发效率。在Java Web开发中,MyBatis作为一个优秀的持久层框架,它支持定制化SQL、存储过程以及...

    通用数据库访问模块,通用DAO类

    通用数据库访问模块(通常称为 DAO,Data Access Object)是一种软件设计模式,用于在应用程序和数据库之间提供一个抽象层。DAO 类的主要目标是隔离业务逻辑层与数据存储层,使得应用程序可以独立于特定的数据库实现...

Global site tag (gtag.js) - Google Analytics