简体   繁体   中英

Hibernate connection problems

I'm working on a webapp and I have connection errors after Hibernate throws exceptions :

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

It gave me this exception each time I try to access my db after an exception occured.

I now Hibernate's not supposed to throw errors if my application is well coded but if something happens with the connection to the db, I don't want my application to be stuck with this error.

Here's my HibernateUtil class :

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

Here's my BaseAction class where initialization and closing of sessions is set :

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

Here's an example of an action:

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

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

Is there a way to avoid the exception above ?

It gave me this exception each time I try to access my db after an exception occurred.

I'm not sure to understand the exact condition. Anyway, after an exception, you should rollback the transaction, close the session and start over. That being said, I have some remarks about your code.

About your HibernateUtil :

  • why do you have a ThreadLocal , the Session#getCurrentSession() method handle that for you (you don't seem to use the thread local though).

  • in HibernateUtil.getCurrentSession() , why do you mess with getCurrentSession() and openSession() ? Firstly, there is no need to do what you do, getCurrentSession() will return a new session if no session is associated to the current thread. Secondly, both approaches are different and have different semantics (you need to close the session yourself when using openSession() ), you should use one or the other.

About your BaseAction :

  • I wonder why you clear() the session after Session#beginTransaction() . In case you didn't committed an ongoing transaction, you'll loose all the pending changes. Is this really what you want?

PS: I would consider using the Open Session in View pattern to remove all this burden from your code.

Resources

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM