锁定老帖子 主题:讨论:在DAO中对Hibernate的封装
该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2004-04-13
同意楼上说的,希望能有人弄出一个图和代码来,这样我们这些水平相对低些的可以理解的更透彻!
|
|
返回顶楼 | |
发表时间:2004-07-20
一个简单的设计,UML图标不是很标准,DAO的一些方法也都没有写出来。还有返回值什么的都没有斟酌
|
|
返回顶楼 | |
发表时间:2004-07-24
kk_kkk 写道 哎,讨论了这么长时间,也没有人牵个头把总结一下Dao封装hibernate的一个合理的可行的方案并整理出代码大家分享一下啊。对那些已经很熟悉hibernate的朋友来说,这个该不是很难的事情吧。讨论技术上的问题是正确的,但是如果有相关的代码作为辅助说明的话,大家理解起来才不会吃力吧?!不知大家怎么认为?
强烈支持!这样对新手很有帮助d! |
|
返回顶楼 | |
发表时间:2004-07-24
Spring对Hibernate进行了封装,
其中的 org.springframework.orm.hibernate.support.HibernateDaoSupport比较符合讨论的主题。 还有: org.springframework.orm.hibernate.LocalSessionFactoryBean org.springframework.orm.hibernate.HibernateTransactionManager 看名字就能猜出它们的作用了。 DAO中的代码大概是这个样子: public class EmployerHibernateDAO extends HibernateDaoSupport implements IEmployerDAO { public EmployerHibernateDAO(); { super();; } public Employer saveOrUpdateEmployer(final Employer employer); { getHibernateTemplate();.saveOrUpdate(employer);; return employer; } // ... } Service中的代码大概是这个样子: public class EmpServiceSpringImpl implements IEmpService { private IEmployeeDAO employeeDAO; private IEmployerDAO employerDAO; private IEmploymentDAO employmentDAO; public EmpServiceSpringImpl(); { super();; } public Employer addEmployer(Employer employer); throws EmpException { try{ getEmployerDAO();.saveOrUpdateEmployer(employer);; } catch (RuntimeException e); { throw new EmpException("Could not addEmployer " + e.toString(););; } return employer; } //... } 什么连接、关闭、提交、回滚。。。统统地不要写了,在xml中说明一下就行了。 对于Spring+Hibernate,我也是初学乍练。有同道中人吗?切磋一下。 btw: 1、在这里提及Spring,不知坛主是否有意见? 2、论坛的时钟好像快了10多分钟,按照这个时间下班。。。 |
|
返回顶楼 | |
发表时间:2004-07-26
Haiqing 写道 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,望多多指教。 |
|
返回顶楼 | |
发表时间:2004-07-27
哇,这么都回复了啊;)
上半年被项目整死,现在有点空了,好好看看先:) 现在我更倾向于使用Spring来处理业务,见我的blog: http://www.skyinn.org/wiki/Wiki.jsp?page=Java_blogentry_270704_1 目前还在学习Spring中,故而很多东西还不知道 |
|
返回顶楼 | |
发表时间:2004-07-27
现在回过头来看看当初自己的这个设计,确实存在太多的弊端,
在我们的项目中,最大的问题不是哪里去获得session等,而是事务的处理, 对于业务层,他并不知道后台persistence层到底是hibernate还是纯jdbc,因为都是面向接口的,透明处理了,然而当需要处理事务的时候就出现麻烦了, 因为如果将session放在业务层,那么势必增加业务层和持久层间的耦合(至少得传session)。。。 而现在我们的做法是使用spring来管理事务等,见上面我的回复, 唉,如果当初就了解点spring的话。。。。。 |
|
返回顶楼 | |
发表时间:2004-08-10
是应该去用Spring,很方便也很透明,对Hibernate的支持也没话说
不过你以前的思路还是给了我很多启发,我也遇到过这个问题,就是事务的判断,如果自己写是需要一些技巧和方法 |
|
返回顶楼 | |
发表时间:2004-08-11
我的写的代码是
/* * Created on 2004-8-9 */ package com.genewoo.hibernate; import java.io.Serializable; import java.util.Iterator; import java.util.List; import net.sf.hibernate.HibernateException; import net.sf.hibernate.LockMode; import net.sf.hibernate.Session; import net.sf.hibernate.Transaction; /** * @author jian_wu */ public abstract class BasicDAO implements IBasicDAO { protected static Session session; private static int tranLevel = 0; private static Transaction transaction; static{ try { session = HibernateSessionFactory.currentSession();; } catch (DataAccessException e); { e.printStackTrace();; } } /** * @throws DataAccessException * */ public BasicDAO(); throws DataAccessException { super();; } protected static void beginCurrentTransaction(); throws HibernateException { tranLevel++; if (transaction == null); { transaction = session.beginTransaction();; } } protected static void endCurrentTransaction(); { endCurrentTransaction(true);; } protected static void endCurrentTransaction(boolean isCommit); { try { if (transaction != null); { if (isCommit); { tranLevel--; if (tranLevel == 0); { transaction.commit();; transaction = null; } } else { tranLevel = 0; transaction.rollback();; transaction = null; } } } catch (HibernateException e); { transaction = null; } } public void insertObjectList(List list); throws DataAccessException { updateList(list, IBasicDAO.ACTION_INSERT);; } public void insertSingleObject(Object object); throws DataAccessException { updateObject(object, IBasicDAO.ACTION_INSERT);; } public void removeObject(Object object); throws DataAccessException { updateObject(object, IBasicDAO.ACTION_REMOVE);; } public void removeObjectList(List list); throws DataAccessException { updateList(list, IBasicDAO.ACTION_REMOVE);; } private void updateList(List list, String action); throws DataAccessException { try { beginCurrentTransaction();; for (Iterator iter = list.iterator();; iter.hasNext();;); { Object vo = (Object); iter.next();; if (action.equalsIgnoreCase(IBasicDAO.ACTION_UPDATE);); { session.saveOrUpdate(vo);; session.flush();; session.lock(vo, LockMode.UPGRADE);; } else { session.delete(vo);; } } endCurrentTransaction();; } catch (HibernateException e); { e.printStackTrace();; throw new DataAccessException("ERROR IN " + action + " List");; } } private void updateObject(Object vo, String action); throws DataAccessException { try { beginCurrentTransaction();; if (action.equalsIgnoreCase(IBasicDAO.ACTION_UPDATE);); { session.saveOrUpdate(vo);; session.flush();; session.lock(vo, LockMode.UPGRADE);; } else { session.delete(vo);; } endCurrentTransaction();; } catch (HibernateException e); { e.printStackTrace();; throw new DataAccessException("ERROR IN " + action + " Object");; } } public Object selectSingleObjectByPK(Class c, Serializable pk); throws DataAccessException { try { return session.get(c, pk);; } catch (HibernateException e); { e.printStackTrace();; throw new DataAccessException("Error get object");; } } public void updateObjectList(List list); throws DataAccessException { updateList(list, IBasicDAO.ACTION_UPDATE);; } public void updateSingleObject(Object object); throws DataAccessException { updateObject(object, IBasicDAO.ACTION_UPDATE);; } } 现在跑起来是没问题的,主要的疑问在于static方面的使用,我在这方面总有些缺乏经验 担心Session和Transaction是非线程安全,如果多线程读写会出现很大的问题,也在考虑是否把对数据的操作都做成静态方法,不知道好不好 |
|
返回顶楼 | |
发表时间:2004-08-14
robbin 写道 我很早以前就说过n次的话题了。搜索一下最早的帖子。
简单的来说,如果你用EJB,那么用容器管理事务;如果不用EJB,那么用ThreadLocal来管理Session和Transaction。Transaction的提交和Session的关闭在ServletFilter里面完成。如果需要在一次用户请求过程中,完成n次Transaction的话(实际上很少发生这样的需求),就在DAOImpl里面提交Transaction。 总之,不管用不用EJB,你所有的Hibernate的代码都是封装在DAOImpl里面的,业务层不需要也不应该出现Hibernate的代码。 这里有误导,即使使用ejb如果事务没有移交到ejb容器的话,也是一定要做threadlocal的,注意以下选择根据需求发生变化,如果并发很大,没有写入问题 光是查询的话也可以不做threadlocal,反之用threadlocal来管理session试必不可少的 |
|
返回顶楼 | |