【问题标题】:Hibernate connection problems休眠连接问题
【发布时间】:2010-09-28 19:37:40
【问题描述】:

我正在开发一个 web 应用程序,但在 Hibernate 引发异常后出现连接错误:

com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after connection closed.

每当我在发生异常后尝试访问我的数据库时,它都会给我这个异常。

如果我的应用程序编码良好,我现在 Hibernate 不应该抛出错误,但如果与数据库的连接发生问题,我不希望我的应用程序被此错误卡住。

这是我的 HibernateUtil 类:

public class HibernateUtil {
  private static Logger log = Logger.getLogger(HibernateUtil.class);
  private static org.hibernate.SessionFactory sessionFactory;
  private static String confFile = "hibernate-test.properties";
  private static final ThreadLocal<Session> threadSession = new ThreadLocal<Session>();

  private HibernateUtil() {

  }

  public static void buildSessionFactory(){
    Configuration configuration = new Configuration();
    synchronized(HibernateUtil.class){
      if(sessionFactory == null){
        try {
          Properties properties = new Properties();
          properties.load(HibernateUtil.class.getClassLoader().getResourceAsStream(confFile));
          configuration.setProperties(properties);
        } catch (Exception e) {
          log.fatal("cannot load the specified hibernate properties file: " + confFile);
          throw new RuntimeException("cannot load the specified hibernate properties file : " + confFile, e);
        }
        sessionFactory = configuration.configure().buildSessionFactory();
      }

      HibernatePBEEncryptorRegistry registry = HibernatePBEEncryptorRegistry.getInstance();

      if(registry.getPBEStringEncryptor("strongHibernateStringEncryptor") == null) {
        StandardPBEStringEncryptor strongEncryptor = new StandardPBEStringEncryptor();
        strongEncryptor.setAlgorithm("PBEWithMD5AndDES"); // not really needed as it is the default
        strongEncryptor.setPassword("aStrongPassword");
        registry.registerPBEStringEncryptor("strongHibernateStringEncryptor", strongEncryptor);
      }
    }
  }

  public static SessionFactory getSessionFactory() {
    if(sessionFactory == null){
      buildSessionFactory();
    }
    return sessionFactory;
  }

  public static Session getCurrentSession(){
    if(!getSessionFactory().getCurrentSession().isOpen())
      getSessionFactory().openSession();
    return getSessionFactory().getCurrentSession();
  }
}

这是我的 BaseAction 类,其中设置了会话的初始化和关闭:

public class BaseAction extends ActionSupport {

  public Session hib_session;

  public void initHibSession() {
    hib_session = HibernateUtil.getCurrentSession();
    hib_session.beginTransaction();
    hib_session.clear();
  }

  public void closeHibSession() {
    hib_session.getTransaction().commit();
  }
}

这是一个动作示例:

Transaction transaction = new Transaction(user, Transaction.Type.REGISTRATION, new HashSet(domains));

initHibSession();
hib_session.save(transaction);
closeHibSession();
transaction_id = transaction.getId();

有没有办法避免上面的异常?

【问题讨论】:

  • 我不明白你为什么要在交易结束后触摸它。
  • @Tony 好像是“应用”事务。
  • @Pascal Thivent 是对的,我会看看他的答案。

标签: java hibernate


【解决方案1】:

每当我在发生异常后尝试访问我的数据库时,它都会给我这个异常。

我不确定具体情况。无论如何,发生异常后,您应该回滚事务,关闭会话并重新开始。话虽如此,我对您的代码有一些评论。

关于您的HibernateUtil

  • 为什么你有一个ThreadLocalSession#getCurrentSession() 方法为你处理(虽然你似乎没有使用本地线程)。

  • HibernateUtil.getCurrentSession(),你为什么要搞乱getCurrentSession()openSession()?首先,不需要做你所做的事情,如果没有session 与当前线程关联,getCurrentSession() 将返回一个新的session。其次,这两种方式不同,语义也不同(使用openSession()时需要自己关闭session),应该使用其中的一种。

关于你的BaseAction

  • 我想知道为什么你clear() 是在Session#beginTransaction() 之后的会话。如果您没有提交正在进行的事务,您将丢失所有未决的更改。这真的是你想要的吗?

PS:我会考虑使用Open Session in View 模式来消除您代码中的所有这些负担。

资源

【讨论】:

  • 我会看看发生异常后的回滚。我不使用 ThreadLocal,它不应该在那里,我的错误。我将尝试只使用 getCurrentSession(),我将摆脱 openSession()。我 clear() 交易,因为它不应该有正在进行的交易,我也会摆脱它。我将看一下“在视图中打开会话”。谢谢!
  • 我使用了“Open Session in View”,它就像一个魅力......再次感谢您!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-08-24
  • 2016-06-16
  • 2014-08-08
  • 2017-09-25
  • 2020-03-02
  • 1970-01-01
  • 2011-06-18
相关资源
最近更新 更多