论坛首页 Java企业应用论坛

讨论:在DAO中对Hibernate的封装

浏览 89129 次
该帖已经被评为精华帖
作者 正文
   发表时间:2003-10-13  
引用
如果JDO2.0规范能够让Gavin King 感到满意的话,那么Hibernate兼容JDO是势在必行的,所以大家还是尽量用DAO吧,以免以后API再改一次
但是我认为hibernate内部已经实现小粒度的dao层,就不必再在hibernate外部包层dao了,这才是o/r mapping的本意,为防止hibernate的api变动(这是Gavin King 的问题),可以把逻辑封装在大一点的业务块中
0 请登录后投票
   发表时间:2003-10-13  
Haiqing 写道
引用
如果JDO2.0规范能够让Gavin King 感到满意的话,那么Hibernate兼容JDO是势在必行的,所以大家还是尽量用DAO吧,以免以后API再改一次
但是我认为hibernate内部已经实现小粒度的dao层,就不必再在hibernate外部包层dao了,这才是o/r mapping的本意,为防止hibernate的api变动(这是Gavin King 的问题),可以把逻辑封装在大一点的业务块中



可否说的更加直白些?怎么在开发中使用hibernate
0 请登录后投票
   发表时间:2003-10-13  
怎样做比较好?每个持久类设计一个DAO还是一堆持久类合起来设计一个DAO?
0 请登录后投票
   发表时间:2003-10-13  
muziq 写道
怎样做比较好?每个持久类设计一个DAO还是一堆持久类合起来设计一个DAO?


看你的业务需求了,从业务流程来推,不要盯着持久类,就给它加上CRUD,这不是做设计。
0 请登录后投票
   发表时间:2003-10-13  
robbin说的不错,那是不是就按照业务相近的操作合到一个DAO里面?
0 请登录后投票
   发表时间:2003-10-13  
贴一段roller中的对Hibernate的封装,再使用中,其DAO层中一个
PersistentStrategy(是接口)变量,
如果是hibernate实现,则其为HibernateStrategy(DAO持久层实现类),
如果不用Hibernate,则改用其他的实现类
在DAO中各种方法就是通过调用这个类来实现各种操作,
比如CRUD基本就全部封装掉了,对于查询,他的query(hql,object[],type[])也足够用了,
其他可以通过getSession()来实现特殊的访问操作,

所以,现在的焦点是如何设计业务层对DAO的访问,而不需要太关心DAO之下的实现了,即使以后Hibernate升级或者甚至你更换了DAO的实现类,对你的业务逻辑层是无需更改的,而如果在你的业务逻辑层中获取Session并传递的化,就将业务逻辑和DAO绑的太紧了

roller中的这个已经很不错了:)

//在我的实现中,ThreadLocalSession是分开的,在HibernateDAO中定义了一些公用的方法,而具体的实现类则继承自HibernateDAO并实现其接口,
目前来说基本满足应用的需求:)

/*
 * Created on Mar 7, 2003
 */
package org.roller.business.hibernate;

import net.sf.hibernate.HibernateException;
import net.sf.hibernate.Session;
import net.sf.hibernate.SessionFactory;
import net.sf.hibernate.type.Type;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.roller.RollerException;
import org.roller.model.PersistenceStrategy;
import org.roller.pojos.PersistentObject;

import java.util.List;


///////////////////////////////////////////////////////////////////////////////
/**
 * Reusable Hibernate implementations of CRUD operations.
 * @author David M Johnson
 */
public class HibernateStrategy implements PersistenceStrategy
{
    private SessionFactory mSessionFactory;
    
    private ThreadLocal mSessionTLS = new ThreadLocal();;
    
    private static Log mLogger =
        LogFactory.getFactory();.getInstance(HibernateStrategy.class);;
        
    
    //-------------------------------------------------------------------------
    
    public HibernateStrategy(SessionFactory factory); throws RollerException
    {
        mSessionFactory = factory;
    }
    
    //-------------------------------------------------------------------------
    
    private boolean isAvailable(); {
        return mSessionTLS.get();!=null;
    }
    
    //-------------------------------------------------------------------------
    
    /** get session for current thread */
    protected Session getSession();
    {
        Session ses = (Session);mSessionTLS.get();;
        if ( ses == null );
        {
            try
            {
                ses = mSessionFactory.openSession();;
                mLogger.debug(Messages.getString(
                    "HibernateStrategy.openedSession");+ses);; 
            }
            catch (HibernateException e);
            {
                mLogger.error(Messages.getString(
                    "HibernateStrategy.exceptionOpeningSession"););;    
                throw new RuntimeException();;
            }
            mSessionTLS.set(ses);;
        }
        return ses;
    }
    
    //-------------------------------------------------------------------------
    
    /** remove session from thread, flush it and close it. */
    public void release(); throws RollerException
    {
        Session ses = (Session);mSessionTLS.get();;
                        
        if ( null == ses ); return; // there is no session to release
                
        mSessionTLS.set(null);; // sets thread's session to null
                
        try
        {
            ses.flush();;
        }
        catch (HibernateException he);
        {
            mLogger.debug(Messages.getString(
                "HibernateStrategy.exceptionClosing");,he);; 
        }
        try
        {
            if ( ses.isOpen(); ); ses.close();;
        }
        catch (HibernateException he);
        {
            mLogger.debug(Messages.getString(
                "HibernateStrategy.exceptionClosing");,he);;
        }
        mLogger.debug("HibernateStrategy.closedSession"+ses);;
    }

    //-------------------------------------------------------------------------
    /**
     * Removes object using an existing transaction.
     * @param clazz Class of object to remove.
     * @param id Id of object to remove.
     * @throws RollerException Error deleting object.
     */
    public void removePersistentObject( String id, Class clazz ); 
        throws RollerException
    {
        if ( id == null );
        {
            throw new RollerException(Messages.getString(
                "HibernateStrategy.nullNotValidId"););; 
        }
        
        if ( clazz == null );
        {
            throw new RollerException(Messages.getString(
                "HibernateStrategy.nullNotValidClass"););; 
        }
        
        // Create persistent instance and delete it
        Object obj;
        try
        {
            obj = getSession();.load(clazz,id);;
            getSession();.delete(obj);;
            getSession();.flush();;
        }
        catch (HibernateException e);
        {                
            String msg = Messages.formatString(
                "HibernateStrategy.exceptionRemoving",id,clazz.getName(););;      
            mLogger.error(msg);; 

            // Gavin: "make sure you never catch + handle an exception and 
            // then keep using the session (ObjectNotFoundException included!);"            
            release();;
            
            throw new RollerException(e);;
        }
    }
 
    //-------------------------------------------------------------------------
    /**
     * Retrieve object, begins and ends its own transaction.
     * @param clazz Class of object to retrieve.
     * @param id Id of object to retrieve.
     * @return Object Object retrieved.
     * @throws RollerException Error retrieving object.
     */
    public PersistentObject retrievePersistentObject(String id, Class clazz); 
        throws RollerException
    {
        if ( id == null );
        {
            throw new RollerException(Messages.getString(
                "HibernateStrategy.nullNotValidId"););; 
        }
        
        if ( clazz == null );
        {
            throw new RollerException(Messages.getString(
                "HibernateStrategy.nullNotValidClass"););; 
        }
        
        Object obj = null;
        Session ses = getSession();;
        try
        {
            obj = (PersistentObject);ses.load( clazz, id );;
        }
        catch (HibernateException e);
        {                
            String msg = Messages.formatString(
                "HibernateStrategy.exceptionRetrieving",id,clazz.getName(););;      
            mLogger.debug(msg,e);; 

            // Gavin: "make sure you never catch + handle an exception and 
            // then keep using the session (ObjectNotFoundException included!);"                        
            release();; 
        }
        return (PersistentObject);obj;
    }

    //-------------------------------------------------------------------------
    /**
     * Store object using an existing transaction.
     * @param obj 
     * @throws RollerException
     */
    public PersistentObject storePersistentObject(PersistentObject obj); 
        throws RollerException
    {
        if ( obj == null ); 
        {
            throw new RollerException(Messages.getString(
                "HibernateStrategy.nullPassedIn"););; 
        }
        
        Session ses = getSession();;       
        try
        {
            // Dave: I tried using ses.saveOrUpdate(); here, but it did not work.
            
            if ( obj.getId(); == null || obj.getId();.trim();.equals(""); ); 
            {
                // Object has never been written to database, so save it.
                // This makes obj into a persistent instance.
                ses.save(obj);;
            }
            
            if ( !ses.contains(obj); );
            {
                // Object has been written to database, but instance passed in
                // is not a persistent instance, so must be loaded into session.
                PersistentObject vo = 
                    (PersistentObject);ses.load(obj.getClass();,obj.getId(););;
                vo.setData(obj);;
                obj = vo;
            }
            // performance killer? -> ses.flush();;
        }
        catch (HibernateException e); 
        {
            String msg = Messages.formatString(
                "HibernateStrategy.exceptionStoring",obj.getId(););;      
            mLogger.error(msg);; 
            
            // Gavin: "make sure you never catch + handle an exception and 
            // then keep using the session (ObjectNotFoundException included!);"                        
            release();;
            
            throw new RollerException(msg,e);;
        }
        return obj;
    }

    //-------------------------------------------------------------------------
    
    public List query( String query, Object[] args, Object[] types); 
        throws RollerException
    {
        return query(query, args, (Type[]);types);;
    }
    
    //-------------------------------------------------------------------------
    
    public List query( String query, Object[] args, Type[] types ); 
        throws RollerException
    {
        if ( query == null );
          {
              throw new RollerException(Messages.getString(
                "HibernateStrategy.nullNotValidQuery"););; 
          }
        
          if ( args == null );
          {
              throw new RollerException(Messages.getString(
                "HibernateStrategy.nullNotValidArgArray"););; 
          }
        
          if ( types == null );
          {
              throw new RollerException(Messages.getString(
                "HibernateStrategy.nullNotValidArrayType"););; 
          }
        
          try
          {    
              if (query.indexOf("$"); > -1); 
              {
                  query = query.replaceAll("\\$\\d+", "\\?");; 
              }        
              return getSession();.find(query,args,types);;
          }
          catch (HibernateException e);
          {
              String msg = Messages.getString("HibernateStrategy.duringQuery");;
              mLogger.error(msg,e);; 
              
              // Gavin: "make sure you never catch + handle an exception and 
              // then keep using the session (ObjectNotFoundException included!);"                        
              release();;
            
              throw new RollerException(msg,e);; 
          }
    }
    
    //-------------------------------------------------------------------------
    
    public List query( String query ); 
        throws RollerException
    {
        try
        {   
            if (query.indexOf("$"); > -1); 
            {
                query = query.replaceAll("\\$\\d+", "\\?");; 
            }
            return getSession();.find(query);;
        }
        catch (HibernateException e);
        {
            String msg = Messages.getString("HibernateStrategy.duringQuery");;
            mLogger.error(msg,e);; 
            
            // Gavin: "make sure you never catch + handle an exception and 
            // then keep using the session (ObjectNotFoundException included!);"                        
            release();;
            
            throw new RollerException(msg,e);; 
        }
    }

    //-------------------------------------------------------------------------
    
    public void commit(); throws RollerException
    {

        try {
            if (isAvailable();); getSession();.flush();;
        }
        catch (HibernateException he); {
            
            // Gavin: "make sure you never catch + handle an exception and 
            // then keep using the session (ObjectNotFoundException included!);"                        
            release();;
            
            throw new RollerException(he);;
        }
    }
    
    //-------------------------------------------------------------------------
    
    public void rollback(); throws RollerException
    {
    }

}

0 请登录后投票
   发表时间:2003-10-13  
引用
roller中的这个已经很不错了:)


在那里可以得到roller的完整代码?
0 请登录后投票
   发表时间:2003-10-13  
kk_kkk 写道
引用
roller中的这个已经很不错了:)


在那里可以得到roller的完整代码?

http://www.rollerweblogger.org/
0 请登录后投票
   发表时间:2003-10-14  
tuskrabbit, 写的很好
0 请登录后投票
   发表时间:2003-10-15  
我也同意 tuskrabbit 的说法。

我在程序里也是使用 DAO 模式来封装数据库操作的,这两天仔细的看了这里的文章,也
修改了我的 DAO 的设计,把我的思路和大家共享下:

先介绍下代码(为了方便理解,我把 对参数的检查和异常处理 的相关部分去掉了):

帐户类,一个 PO:
Account {
    String username;
    String password;
}


DAO 接口
interface AccountDAO {
    public void addAccount( Account account );;
    public void updateAccount( Account account );;
    public void removeAccount( String username );;
    public Account findByUsername( String username );;
}


AccountDAO 的实现
class AccountDAOHibernate {
    public void addAccount( Account account ); {
       HibernateUtil.add( account );;
    }
    public void updateAccount( Account account ); {
       HibernateUtil.update( account );;
    }
    public void removeAccount( String username ); {
       HibernateUtil.remove( Account.class, username );;
    }
    public Account findByUsername( String username ); {
       account = (Account); HibernateUtil.findById( Account.class, username );;
    }
}



HibernateUtil 是对 Hibernate 的基本 crud 操作的封装
我参考了 poll 的实现
class HibernateUtil {
    public static void add( Object object ); throws HibernateException {
        Session s = HibernateSessionFactory.currentSession();;
        s.save( object );;
        s.flush();;
    }
    public static void update( Object object ); throws HibernateException {
        Session s = HibernateSessionFactory.currentSession();;
        s.saveOrUpdate( object );;
        s.flush();;
    }
    public static void remove(Class clazz, String id); throws HibernateException {
        Session s = HibernateSessionFactory.currentSession();;
        Object object = s.load(clazz, id);;
        s.delete( object );;
        s.flush();;
    }
    public static Object findById( Class clazz, String id ); throws HibernateException {
        Object obj = null;
        Session s = HibernateSessionFactory.currentSession();;
        obj = s.load( clazz, id );;
        s.flush();;
        return obj;
    }
}



HibernateSessionFactory 使用 ThreadLocal 做 Session 管理,实现和 hibernate 网站上的一样
参考:http://hibernate.bluemars.net/42.html
class HibernateSessionFactory {
    public static final ThreadLocal session = new ThreadLocal();;
    private static SessionFactory sessionFactory;
    private static Configuration conf;
    public static void init(); {
        conf = new Configuration();.configure();;
        sessionFactory = conf.buildSessionFactory();;
    }
    public static Session currentSession(); {
        Session s = (Session); session.get();;
        if (s == null); {
            s = sessionFactory.openSession();;
            session.set(s);;
        }
        return s;
    }
    public static void closeSession(); {
        Session s = (Session); session.get();;
        session.set(null);;
        if (s != null); s.close();;
    }
}




说明:
1.DAO 模式的目的是为了把数据库操作封装在 DAO 层下
  Session 应该被封装在 DAO 层里

2.何时关闭 Session:
  由于使用了 ThreadLocal 来管理 Session,我没有在 DAO 的方法里关闭 Session
  这样,同一个 thraed 里的各个 DAO 方法可以访问到 同一个 Session,可以利用
  Hibernate 的 lazy load 功能。
  在 web 应用程序里可以使用 HibernateFilter 来处理 Session 的关闭:
  参考:http://hibernate.bluemars.net/110.html
 
public class HibernateFilter implements Filter {
    public void init(FilterConfig filterConfig); throws ServletException {
        HibernateSessionFactory.init();;
    }
    public void doFilter( ... ); {
        try{
            filterChain.doFilter( servletRequest, servletResponse );;
        } finally {
            try {
                HibernateSessionFactory.closeSession();;
            } catch (HibernateException e); {
                log.error( "Error closing current session " + e );;
            }
        }
    }
    public void destroy(); {
    }
}

 
 
3.对 Transaction 的处理
  不在 DAO 层处理 Transaction
  如果确实需要 Transaction ,在上一层,比如业务层里的 Session Bean 里来做。
0 请登录后投票
论坛首页 Java企业应用版

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