请教一个问题,困惑一个多礼拜了:
我在使用Hibernate3做一个论坛,Hibernate Synchronizer自动生成的DAO加上手写的论坛服务接口(包含发帖,添加面板等方法),论坛服务接口里面的方法会通过DAO实现,现在遇到了这样的问题,自动生成的DAO里面包含了session的打开与关闭操作,有的书上说DAO里面的sessin关闭操作要注释掉,用HibernateTemplate加回调实现论坛服务接口,问了好多朋友都说DAO里面session的操作要保留,在坛子里也看到过一篇相关文章,坛友的回复几乎都是建议保留,但是保留的情况下如果我启用lazy机制,那么论坛服务接口中有些涉及关联操作的方法就会延迟加载的错误,比如:测试中,先从库中load一个版面,再为其添加子版面,下面代码是添加子版面:
public void addChildBoard(final Board parent,final Board child) {
BoardDAO boardDAO = (BoardDAO)BoardDAO.getInstance();
child.setParent(parent);
parent.getChildBoards().add(child);
boardDAO.save(child);
}
先获得版面DAO,然后设置关联操作,最后保存child版面,由于版面跟自身是一对多的映射关系,那么在parent.getChildBoards()的时候,会执行数据库操作,可是在load版面之后session往往已经关闭了,就会报延迟加载的错误,如果lazy修改成false可以通过,但是版面毕竟有限可以用lazy=false,如果延迟调用帖子的话,是不是就不能用false了,所以,现在我不知道是该修改DAO中的关于session的操作,还是不修改关于session的操作另有其他办法实现论坛服务接口中存在关联操作的方法,总的原则是我不想在View层出现Hibernate代码(如session的管理)。
第一次发问,多贴点分,大家帮帮忙,先谢了。

解决方案 »

  1.   


    import org.hibernate.HibernateException;
    import org.hibernate.Session;
    import org.hibernate.cfg.Configuration;/**
     * Configures and provides access to Hibernate sessions, tied to the
     * current thread of execution.  Follows the Thread Local Session
     * pattern, see {@link http://hibernate.org/42.html }.
     */
    public class HibernateSessionFactory {    /** 
         * Location of hibernate.cfg.xml file.
         * Location should be on the classpath as Hibernate uses  
         * #resourceAsStream style lookup for its configuration file. 
         * The default classpath location of the hibernate config file is 
         * in the default package. Use #setConfigFile() to update 
         * the location of the configuration file for the current session.   
         */
        private static String CONFIG_FILE_LOCATION = "/hibernate.cfg.xml";
    private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();
        private  static Configuration configuration = new Configuration();
        private static org.hibernate.SessionFactory sessionFactory;
        private static String configFile = CONFIG_FILE_LOCATION; static {
         try {
    configuration.configure(configFile);
    sessionFactory = configuration.buildSessionFactory();
    } catch (Exception e) {
    System.err
    .println("%%%% Error Creating SessionFactory %%%%");
    e.printStackTrace();
    }
        }
        private HibernateSessionFactory() {
        }

    /**
         * Returns the ThreadLocal Session instance.  Lazy initialize
         * the <code>SessionFactory</code> if needed.
         *
         *  @return Session
         *  @throws HibernateException
         */
        public static Session getSession() throws HibernateException {
            Session session = (Session) threadLocal.get(); if (session == null || !session.isOpen()) {
    if (sessionFactory == null) {
    rebuildSessionFactory();
    }
    session = (sessionFactory != null) ? sessionFactory.openSession()
    : null;
    threadLocal.set(session);
    }        return session;
        } /**
         *  Rebuild hibernate session factory
         *
         */
    public static void rebuildSessionFactory() {
    try {
    configuration.configure(configFile);
    sessionFactory = configuration.buildSessionFactory();
    } catch (Exception e) {
    System.err
    .println("%%%% Error Creating SessionFactory %%%%");
    e.printStackTrace();
    }
    } /**
         *  Close the single hibernate session instance.
         *
         *  @throws HibernateException
         */
        public static void closeSession() throws HibernateException {
            Session session = (Session) threadLocal.get();
            threadLocal.set(null);        if (session != null) {
                session.close();
            }
        } /**
         *  return session factory
         *
         */
    public static org.hibernate.SessionFactory getSessionFactory() {
    return sessionFactory;
    } /**
         *  return session factory
         *
         * session factory will be rebuilded in the next call
         */
    public static void setConfigFile(String configFile) {
    HibernateSessionFactory.configFile = configFile;
    sessionFactory = null;
    } /**
         *  return hibernate configuration
         *
         */
    public static Configuration getConfiguration() {
    return configuration;
    }}这个是代码是获取和关闭session。
    因为session是线程不安全的,所以用ThreadLocal 对象来管理每一个session。一次请求从开始到jsp显示结束是一个线程。在本次线程里的session是安全的,所以dao操作后不要关闭session,那么在哪里关呢,当然是此次线程结束的时候  也就是请求完全处理了以后,那么我们通常是用文件过滤来控制,看下面的过滤。import java.io.IOException;import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;import cn.com.wanghai.dao.HibernateSessionFactory;
    public class FilefilterForHibernateAndEncoding implements Filter { public void destroy() {
    // TODO Auto-generated method stub } public void doFilter(ServletRequest request, ServletResponse response,
    FilterChain filterChain) throws IOException, ServletException {

    request.setCharacterEncoding("gb2312");//这个是过滤字符集
    response.setCharacterEncoding("gb2312");//这个是过滤字符集
    try{
    filterChain.doFilter(request, response);
    }catch(Exception e){
    e.printStackTrace();
    }finally{
    System.out.println("session关闭前");
    HibernateSessionFactory.closeSession();
    System.out.println("session关闭后");
    }
    } public void init(FilterConfig arg0) throws ServletException {
    // TODO Auto-generated method stub }}
    加上过滤器
    <filter>
       <filter-name>hibernate_session_encoding</filter-name>
       <filter-class>cn.com.wanghai.filefilter.FilefilterForHibernateAndEncoding</filter-class>
      </filter>
      <filter-mapping>
       <filter-name>hibernate_session_encoding</filter-name>
       <url-pattern>/*</url-pattern>
      </filter-mapping>
    我就是这样做的  也是跟别人学的  希望有帮助。
      

  2.   

    谢谢小海,很有帮助,我再看看有没有不DAO中不关闭Session的方法。
      

  3.   

    不用hql和cascade
    自己写sql用creitia接口拼出来
      

  4.   

    你百度一下OpenSessionInView 吧,回答无数次这个问题了有点恶心了
    相关的你看看.
    http://topic.csdn.net/u/20080119/14/78afd3c0-2161-412c-940a-12664c4640f5.html
    http://topic.csdn.net/u/20080607/15/b83a97c6-58f5-43b5-80d8-a48c96ac7559.html
    http://topic.csdn.net/u/20080605/21/9f99fd25-0c7e-463a-b510-99d3e3671b64.html
    http://topic.csdn.net/u/20080603/21/78926a4b-38d5-4382-ad2d-096ac094f017.html
    http://topic.csdn.net/u/20080603/21/78926a4b-38d5-4382-ad2d-096ac094f017.html