锁定老帖子 主题:讨论:在DAO中对Hibernate的封装
该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2003-09-15
用一个HibernateDAO封装一些共同的操作: package org.skyinn.commons.dao; import net.sf.hibernate.HibernateException; import net.sf.hibernate.Session; import net.sf.hibernate.Transaction; /** * <p>HibernateDAO.</p> * * <b>Description:</b> * 封装Hibernate的会话、事务的通用操作,以简化相应DAO中的相关操作。 * * 具体实现DAO的示例代码如下: * <code><pre> * public Account register(final Account account); throws DAOException { * try { * //事务开始 * beginTransaction();; * //具体操作 * //注册帐号 * //getSession();.save(account);; * //结束事务 * endTransaction(true);; * } catch (HibernateException he); { * //但发生异常时事务回滚 * rollback();; * log.error(he);; * //向调用者抛出异常 * throw new DAOException(he);; * } finally { * //结束会话 * closeSession();; * } //end try...catch...finally.... * return account; * } //end register(); * </pre></code> * * @author HanQing * @version $Revision: 1.3 $ $Date: 2003/08/08 11:44:31 $ */ public abstract class HibernateDAO implements DAO { protected Session session = null; protected Transaction transaction = null; /** * Returns the session. * @return Session */ public Session getSession(); { return session; } /** * Returns the transaction. * @return Transaction */ public Transaction getTransaction(); { return transaction; } /** * 开始事务。 * * @throws HibernateException 创建事务时的异常 */ public void beginTransaction(); throws HibernateException { //创建对话 session = HibernateSessionFactory.openSession();; //事务开始 transaction = session.beginTransaction();; }//end beginTransaction(); /** * 结束事务。 * * @param commit 是否提交,但只是读取操作时不需要事务提交,故设为false以提高相应速度 * @throws HibernateException 结束事务时的Hibernate异常 * @throws DAOException 结束会话时的DAO异常 */ public void endTransaction(boolean commit); throws HibernateException,DAOException { if (commit); { transaction.commit();; } else { // Don't commit the transaction, can be faster for read-only operations transaction.rollback();; } closeSession();; }//end endTransaction(); /** * 事务回滚,但事务出错时回滚当前操作。 * * @throws DAOException 回滚中出现的异常 */ public void rollback(); throws DAOException{ if(null != transaction);{ try { transaction.rollback();; } catch (HibernateException e); { throw new DAOException(e);; } } }//end rollback(); /** * 结束会话。 * * @throws DAOException 结束会话时出现的异常 */ public void closeSession(); throws DAOException{ try { session.close();; } catch (HibernateException e); { throw new DAOException(e);; } }//end closeSession(); }//EOC HibernateDAO 在具体的DAO中,用有个DAO接口来定义方法(如AccountDAO), 从HiberanteDAO继承并实现AccountDAO,做具体的持久层操作: package org.skyinn.test.user.dao; import org.skyinn.commons.dao.DAOException; import org.skyinn.commons.dao.HibernateDAO; import org.skyinn.commons.test.user.bean.Account; import net.sf.hibernate.HibernateException; import net.sf.hibernate.Query; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.util.Iterator; /** * <p>AccountDAO的Hibernate实现。</p> * * @version $Revision: 1.6 $ $Date: 2003/08/09 09:41:33 $ * @author $Author: hanqing $ */ public final class AccountDAOHibImpl extends HibernateDAO implements AccountDAO { /**日志。*/ private static Log log = LogFactory.getLog(AccountDAOHibImpl.class);; //~ Methods ================================================================ public Account findAccount(String accountName); throws DAOException{ Account account = null; final String queryString = "select account from Account as account " + " where account.accountName = :accountName"; try { //验证帐号 beginTransaction();; final Query query = getSession();.createQuery(queryString);; //设置参数 query.setString("accountName", accountName);; //Execute Query... final Iterator it = query.iterate();; if (it.hasNext();); { account = (Account); it.next();; } //结束事务,false表示不提交 endTransaction(false);; } catch (HibernateException he); { //但发生异常时事务回滚 rollback();; log.error(he);; throw new DAOException(he);; } finally { //结束会话 closeSession();; } //end try...catch...finally.... return account; }//end findAccount(); public Account findAccount(long accountId); { return null; } /** * @see AccountDAO#register */ public Account register(final Account account); throws DAOException { try { //事务开始 beginTransaction();; //创建帐号 session.save(account);; //结束事务 endTransaction(true);; } catch (HibernateException he); { //但发生异常时事务回滚 rollback();; log.error(he);; throw new DAOException(he);; } finally { //结束会话 closeSession();; } //end try...catch...finally.... return account; } //end register(); /** * @see AccountDAO#login */ public Account login(final Account account); throws DAOException { Account _account = null; final String queryString = "select account from Account as account " + " where account.accountName = :accountName" + " and account.password = :password"; try { //验证帐号 beginTransaction();; final Query query = getSession();.createQuery(queryString);; //设置参数 query.setString("accountName", account.getAccountName(););; query.setString("password", account.getPassword(););; //Execute Query... final Iterator it = query.iterate();; if (it.hasNext();); { _account = (Account); it.next();; } //结束事务,false表示不提交 endTransaction(false);; } catch (HibernateException he); { //但发生异常时事务回滚 rollback();; log.error(he);; throw new DAOException(he);; } finally { //结束会话 closeSession();; } //end try...catch...finally.... return _account; } //end login(); } //EOC AccountDAOHibImpl 在业务逻辑层中通过DAO工厂来取这些DAO并执行之,这里有几个问题不是很确信: 1:在DAO中每个方法都需要创建一个session和tx,这在一般应用中问题不大,我考虑的是但业务逻辑层有如果需要调用多个DAO的方法时,岂不需要多个session和tx,这样其实也就美了事务的的操作了,所以想请教有没有好的解决方案;) 2:昨天才想到,其实对对象的CRUD来说,CUD方法非常的类似, 而通过Hiberante一封装,变得更抽象了,比如CREATE方法都可以抽象成: ... //事务开始 beginTransaction();; //创建对象 session.save(obj);; //结束事务 endTransaction(true);; ... 但还没做更进一步的研究和试验,不知道是否可以实现,如果可以的话,把这三个方法再往上一抽,剩下的DAO实现中就只要完成一些查询等就够了,HOHO,哪岂不很爽》?呵呵:)回头试试去:) 嗯,还有很多问题,大家一起来讨论下:) 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2003-09-15
DAO层的类层次结构:
|
|
返回顶楼 | |
发表时间:2003-09-15
换一个全一点的:)
|
|
返回顶楼 | |
发表时间:2003-09-16
我其实不是很同意你的封装方法,当然意见可以有分歧,不过你的思路很不错,所以放进精华文章。
面向对象应该根据业务逻辑来封装对象,而不是按照使用的API来封装,我的面向对象的设计思路都写在 《面向对象的思维方法》 http://hibernate.fankai.com/viewtopic.php?t=38 里面。我考虑封装的出发点和你不太一样的。 引用 1:在DAO中每个方法都需要创建一个session和tx,这在一般应用中问题不大,我考虑的是但业务逻辑层有如果需要调用多个DAO的方法时,岂不需要多个session和tx,这样其实也就美了事务的的操作了,所以想请教有没有好的解决方案;)
可以用ThreadLocal 来管理Session,论坛有这方面的几个帖子,你用论坛搜索功能搜一下。 |
|
返回顶楼 | |
发表时间:2003-09-16
TO:robbin
本来就是拿来讨论的,呵呵, 现在还没研究过TreadLocal,回头看看去 to:cxhz_cn 用DAO可以对业务逻辑称屏蔽具体的持久层实现, 比如AccountDAO,这只是个接口,在业务逻辑中只使用这个接口,而具体的实现则有DAO工厂提供,所以但你换一种持久层实现的时候非常方便,我曾经用配置文件来做过,可以在程序运行环境下更换不同的DAO实现以,可以访问不同的数据源,呵呵:) BTW:看你的ID是不是杭州的? |
|
返回顶楼 | |
发表时间:2003-09-19
用DAO封装Hibernate的操作是个很不错的设计。由于在大型的架构里,DAO作为业务处理的原子操作层,在其之上,我们需要一层综合的业务处理层来完成高级的业务方法。而这些高级业务操作一般都采用SessionBean来实现,所以建议把你的DAO里的事务处理放到这些高级业务方法里来完成。举个例子:
很多场合我们需要建立客户资料。而往往在设计的时候就把客户资料做成了客户基本资料、客户的扩展资料等不同的对象。这些对象的操作都是封装在DAO里的。有CustomerBaseDAO、LinkmanDAO。这样如果我们有一个高级业务方法:创建客户。则该业务方法就可以采用两种事务处理: 1、容器管理的事务 2、JTA 两种方式做起来都比你把事务处理放到每个DAO里来得好得多。这样系统的层次结构也十分的清楚。 |
|
返回顶楼 | |
发表时间:2003-09-19
tks tuskrabbit:)
|
|
返回顶楼 | |
发表时间:2003-10-06
robbin 写道 我其实不是很同意你的封装方法,当然意见可以有分歧,不过你的思路很不错,所以放进精华文章。
面向对象应该根据业务逻辑来封装对象,而不是按照使用的API来封装,我的面向对象的设计思路都写在 《面向对象的思维方法》 http://hibernate.fankai.com/viewtopic.php?t=38 里面。我考虑封装的出发点和你不太一样的。 引用 1:在DAO中每个方法都需要创建一个session和tx,这在一般应用中问题不大,我考虑的是但业务逻辑层有如果需要调用多个DAO的方法时,岂不需要多个session和tx,这样其实也就美了事务的的操作了,所以想请教有没有好的解决方案;)
可以用ThreadLocal 来管理Session,论坛有这方面的几个帖子,你用论坛搜索功能搜一下。 我没看过hibernate源码,但感觉hibernate已经封装了domain store,完成了底层dao的持久化,所以完全可以把映射类直接参与业务逻辑transparently,而不必再次把hibernate类封装在dao模式中,当然会有诸如session.update()等难以避免的操作。我才接触hibernate,望多多指教。 |
|
返回顶楼 | |
发表时间:2003-10-07
l_yeung 写道 AOP 也是不错的选择
或许IoC是更加不错的选择 |
|
返回顶楼 | |
发表时间:2003-10-09
大家还有别的更好的设计没有呢,拿出来讨论一下可好
|
|
返回顶楼 | |