升级到Hibernate 4.1和“臭名昭着”的HibernateTemplate

2022-09-02 04:43:36

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

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

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

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

谢谢。

相关阅读:

  1. 冬眠与春季 - 冬眠模板历史
  2. 休眠核心迁移指南
  3. 迁移到 SPRING 3.1 并休眠 4.1
  4. org.springframework.orm.hibernate3.HibernateTemplate

答案 1

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

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

新的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");
        }
    }

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


答案 2

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

关于引入回归错误,升级库将始终存在风险,特别是当它是休眠应用程序的核心时。我能给出的唯一建议是,在升级之前,请确保您的测试套件具有不错的覆盖范围。毕竟,这是测试套件的工作 - 捕获回归错误。


推荐