Проблемы со связью в спящем режиме - PullRequest
1 голос
/ 28 сентября 2010

Я работаю над веб-приложением и у меня возникают ошибки соединения после того, как 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();

Есть ли способ избежать исключения выше?

1 Ответ

1 голос
/ 29 сентября 2010

Это выдавало мне это исключение каждый раз, когда я пытаюсь получить доступ к своей БД после возникновения исключения.

Я не уверен, чтобы понять точное условие. В любом случае, после исключения вы должны откатить транзакцию, закрыть сеанс и начать заново. При этом у меня есть несколько замечаний по поводу вашего кода.

О вашем HibernateUtil:

  • почему у вас есть ThreadLocal, метод Session#getCurrentSession(), который вам подходит (хотя вы, кажется, не используете локальный поток).

  • в HibernateUtil.getCurrentSession(), почему вы связываетесь с getCurrentSession() и openSession()? Во-первых, нет необходимости делать то, что вы делаете, getCurrentSession() вернет новый session, если с текущим потоком не связано session. Во-вторых, оба подхода различны и имеют разную семантику (вам нужно закрывать session самостоятельно при использовании openSession()), вы должны использовать один или другой.

О вашем BaseAction:

  • Интересно, почему вы clear() сеанс после Session#beginTransaction(). Если вы не совершили текущую транзакцию, вы потеряете все ожидающие изменения. Вы действительно этого хотите?

PS: Я бы хотел использовать шаблон Open Session in View , чтобы снять всю эту нагрузку с вашего кода.

Ресурсы

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...