21

我正在将我们的项目从 Hibernate 3.0 升级到 Hibernate 4.1.6。(我们目前使用的是spring 3.1)

我在许多文章和 HibernateTemplate 文档中读到,由于不支持 4.0 版 HibernateTemplate,我应该用调用sessionFactory.getCurrentSession()来获取会话来替换它的用法。

由于这个项目是从旧版本的 Hibernate 开始的,因此鼓励使用,我们目前在整个项目HibernateTemplate中有 124 次使用。HibernateTemplate我担心替换所有这些事件sessionFactory.getCurrentSession()可能会在我们的项目中插入回归错误。此外,有些地方在HibernateTemplate非事务性上下文中使用,没有“当前”会话。在这些情况下我该怎么办?打开一个新会话并自己处理(关闭)它?我用的时候不是这样的HibernateTemplate

你有解决这些问题的好策略吗?

谢谢。

相关阅读:

  1. 休眠与。Spring - HibernateTemplate 历史
  2. Hibernate 核心迁移指南
  3. 迁移到 Spring 3.1 和 HIBERNATE 4.1
  4. org.springframework.orm.hibernate3.HibernateTemplate
4

3 回答 3

11

好的,这就是我实际所做的,我不知道这是否是解决此问题的最佳解决方案,但在我们的情况下,并且由于我一直在寻找最本地化的解决方案,因此对我来说似乎是最好的。

我扩展了 springframework.orm.hibernate3.HibernateTemplate 并创建了一个新的 MyHibernateTemplate。新模板的主要作用是覆盖大多数 hibernate3.HibernateTemplate 最终导致的 doExecute 方法,并提供旧 SessionFactoryUtils 提供的一些功能(如 isSessionTransactional 和 applyTransactionTimeout)。

新的 doExecute 复制了旧的逻辑,但不是 SessionFactoryUtils.getNewSession 来获取会话,而是首先尝试查找打开的会话 getSessionFactory().getCurrentSession() :

boolean newSessionOpened = false;
Session session;

if (enforceNewSession){
    session = SessionFactoryUtils.openSession(getSessionFactory());
    newSessionOpened = true;
} else {
    try {
        // look for an open session
        session = getSessionFactory().getCurrentSession();
    }
    catch (HibernateException ex) {
        try {
            // if there isn't an open session, open one yourself
            session = getSessionFactory().openSession();
            newSessionOpened = true;
        } catch (HibernateException e) {
            throw new DataAccessResourceFailureException("Could not open Hibernate Session", ex);
        }
    }
}

// is the open session, is a session in a current transaction?
boolean existingTransaction = (!enforceNewSession &&
        (!isAllowCreate() || isSessionTransactional(session, getSessionFactory())));

您只需要手动关闭此会话:

    finally {
    // if session was used in an existing transaction restore old settings
    if (existingTransaction) {
        //logger.debug("Not closing pre-bound Hibernate Session after HibernateTemplate");
        disableFilters(session);
        if (previousFlushMode != null) {
            session.setFlushMode(previousFlushMode);
        }
    }
    // if not and a new session was opened close it
    else {
        // Never use deferred close for an explicitly new Session.
        if (newSessionOpened) {
            SessionFactoryUtils.closeSession(session);
            //_log.info("Closing opened Hibernate session");
        }
    }

我试图保持这个答案简短,但如果有任何问题,我可以进一步详细说明这个问题。

于 2012-10-02T17:44:36.170 回答
2

在文档中查看此部分。它说这SessionFactory.getCurrentSession()是可插入的,并且有一个ThreadLocalSessionContext实现将“当前会话”保留在 JTA 事务中ThreadLocal而不是 JTA 事务中。ThreadLocalSessionContext 还将在从该会话创建的休眠事务结束时关闭会话,因此您不必担心Session自己关闭。

关于引入回归错误,升级库总是有风险的,特别是当它是你的应用程序的核心时,如休眠。我能给出的唯一建议是确保您的测试套件在升级之前具有良好的覆盖率。毕竟,这是您的测试套件的工作——捕捉回归错误。

于 2012-08-28T19:42:32.977 回答
0

您也可以继续使用HibernateTemplatewith getCurrentSession(),因为在许多情况下openSession()可能不是最佳选择,因为您需要自行关闭会话。要使用 currentSession,您可以添加以下内容来管理事务:

<prop key="hibernate.transaction.jta.platform">org.hibernate.engine.transaction.jta.platform.internal.JBossAppServerJtaPlatform</prop>

其中键的值将取决于您的 AS。

于 2019-05-30T07:06:52.560 回答