1

我正在修改一个较旧的 Spring 项目,以更多地反映 Spring 3.0.x 中应该如何完成的事情。

我所做的更改之一是对存储库/dao 层。按照最佳实践的建议,我不再从HibernateDaoSupport使用扩展HibernateTemplate,而是SessionFactory直接通过 using使用 Hibernate sessionFactory.getCurrentSession(),它应该与 Spring 3.0.x 及更高版本一起使用。

这对整个项目来说是一个非常大的好处,因为它摆脱了由HibernateTemplate. 但是,我刚刚注意到我不能再调用使用 @PostConstruct 的 Service 方法(或者onStartUp在 XML 应用程序上下文中使用 bean 的属性)

例如,这个方法过去使用 运行得很好HibernateTemplate,但现在 Hibernate 抛出一个异常,抱怨没有会话绑定到线程:

@Override
@PostConstruct
public void onStartUp() {
    logger.debug("Starting Bootstrap Service...");

    createSysAdminUser();
    createDefaultRoles();
    createDefaultThemes();

    createStopListIfDoesNotExist();
    stopListService.load();

    partialMappingService.load();
    dictionaryService.load();
}

我可以删除这个@PostConstruct方法调用......它是系统中唯一的一个。当应用程序启动以引导新应用程序的数据时调用它。大多数时候,它在生产系统上什么都不做,但是将它用于新创建的测试和开发数据库很方便。

关于为什么以及如何解决它的任何想法?

谢谢!

编辑:这是我的事务管理建议配置:

<aop:config>
    <aop:advisor advice-ref="transactionAdvice"
                 pointcut="execution(* *..service.*.*(..))" order="1"/>
    <!-- gets sub packages like service.user -->
    <aop:advisor advice-ref="transactionAdvice"
                 pointcut="execution(* *..service.*.*.*(..))" order="2"/>
</aop:config>

<tx:advice id="transactionAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="find*" read-only="true" propagation="REQUIRED"/>
        <tx:method name="get*" read-only="true" propagation="REQUIRED"/>
        <tx:method name="*" propagation="REQUIRED"/>
    </tx:attributes>
</tx:advice>
4

1 回答 1

1

HibernateDaoSupport 类文档中所述,“如果传入 SessionFactory,此类将创建自己的 HibernateTemplate 实例。默认情况下,该 HibernateTemplate 上的 'allowCreate' 标志将是 'true'。” 这意味着在旧系统下,您的 DAO 可以按需打开会话,而不受任何实际控制。

当 Spring 管理 SessionFactory 时,它会安装一个SpringSessionContext作为 Hibernate 的CurrentSessionContext。现在,当您调用时SessionFactory.getCurrentSession(),SpringSessionContext 在 Spring 管理的 ThreadLocal 中查找 Session,如果不存在则失败。会话通常以以下两种方式之一打开并放置在那里:使用 open-session-in-view 模式在每个新请求时都会这样做,并且启动事务也会这样做。在您的情况下,您没有执行代码来响应请求,因此 OSIV 没有发挥作用,而且您显然也没有处于活动事务中。使方法具有事务性将解决您的问题。

于 2013-02-19T05:20:47.570 回答