初始化hibernate 时可能出现重复读取hibernate配置文件导致报错的解决办法

假设你有一个应用程序,登录系统时会初始化很多信息,比如使用ajax同时初始化两类信息,这时如果你的hibernate还没初始化信息,就会有两个线程同时进行初始化操作。这时hibernate就会发现两个相同的hbm配置文件 被读取,所以,问题发生了。

这怪谁?其实是我们自己的问题,如果你出现了上面的问题,就需要看看你的获取session的机制是否正常了

这是使用myeclipse自动生成的session工厂类:

package com.dcsoft.sbgl.hibernate;

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 threadLocal = new ThreadLocal();
    private  static Configuration configuration = new Configuration();
    private static org.hibernate.SessionFactory sessionFactory;
    private static String configFile = CONFIG_FILE_LOCATION;

    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;
 }

}

 

请看一下标红的部分:

if (sessionFactory == null)

这时就会进行初始化操作,如果两个线程同时到了这里,嘿嘿…………

解决方法:

1 初始化:在启动应用的时候配置一个servlet进行初始化hibernate操作,无论做什么都行,只要使用hibernate进行数据库操作。

如果你觉得这种方法还不保险,那就使用第二招:加锁!

2 将红色部分加上:

    public static Session getSession() throws HibernateException {
        Session session = (Session) threadLocal.get();

  if (session == null || !session.isOpen()) {

  synchronized (lockObj) {
     if (sessionFactory == null) {
      rebuildSessionFactory();
     }

}
   session = (sessionFactory != null) ? sessionFactory.openSession()
     : null;
   threadLocal.set(session);
  }

        return session;
    }

但总感觉这种方法会影响效率,感觉能用第一种方法最好

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值