论坛首页 Java企业应用论坛

讨论:在DAO中对Hibernate的封装

浏览 89137 次
该帖已经被评为精华帖
作者 正文
   发表时间:2004-04-13  
同意楼上说的,希望能有人弄出一个图和代码来,这样我们这些水平相对低些的可以理解的更透彻!
0 请登录后投票
   发表时间:2004-07-20  
一个简单的设计,UML图标不是很标准,DAO的一些方法也都没有写出来。还有返回值什么的都没有斟酌
0 请登录后投票
   发表时间:2004-07-24  
kk_kkk 写道
哎,讨论了这么长时间,也没有人牵个头把总结一下Dao封装hibernate的一个合理的可行的方案并整理出代码大家分享一下啊。对那些已经很熟悉hibernate的朋友来说,这个该不是很难的事情吧。讨论技术上的问题是正确的,但是如果有相关的代码作为辅助说明的话,大家理解起来才不会吃力吧?!不知大家怎么认为?

强烈支持!这样对新手很有帮助d!
0 请登录后投票
   发表时间: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多分钟,按照这个时间下班。。。
0 请登录后投票
   发表时间: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,望多多指教。
0 请登录后投票
   发表时间:2004-07-27  
哇,这么都回复了啊;)
上半年被项目整死,现在有点空了,好好看看先:)


现在我更倾向于使用Spring来处理业务,见我的blog:
http://www.skyinn.org/wiki/Wiki.jsp?page=Java_blogentry_270704_1

目前还在学习Spring中,故而很多东西还不知道
0 请登录后投票
   发表时间:2004-07-27  
现在回过头来看看当初自己的这个设计,确实存在太多的弊端,
在我们的项目中,最大的问题不是哪里去获得session等,而是事务的处理,
对于业务层,他并不知道后台persistence层到底是hibernate还是纯jdbc,因为都是面向接口的,透明处理了,然而当需要处理事务的时候就出现麻烦了,
因为如果将session放在业务层,那么势必增加业务层和持久层间的耦合(至少得传session)。。。


而现在我们的做法是使用spring来管理事务等,见上面我的回复,


唉,如果当初就了解点spring的话。。。。。
0 请登录后投票
   发表时间:2004-08-10  
是应该去用Spring,很方便也很透明,对Hibernate的支持也没话说

不过你以前的思路还是给了我很多启发,我也遇到过这个问题,就是事务的判断,如果自己写是需要一些技巧和方法
0 请登录后投票
   发表时间: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是非线程安全,如果多线程读写会出现很大的问题,也在考虑是否把对数据的操作都做成静态方法,不知道好不好
0 请登录后投票
   发表时间: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试必不可少的
0 请登录后投票
论坛首页 Java企业应用版

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