我正在重新设计一个较旧的Spring项目,以更好地反映在Spring 3.0.x中应该如何完成的事情。
我做的一个更改是存储库/ dao层。根据最佳做法的建议,我不再从HibernateDaoSupport
延伸到使用HibernateTemplate
,而是使用SessionFactory
直接使用Hibernate sessionFactory.getCurrentSession()
,这应该可以正常工作使用Spring 3.0.x及更高版本。
这对整个项目来说是一个非常大的好处,因为它摆脱了由HibernateTemplate
引起的所有包装代码。但是,我只是注意到我不能再调用使用@PostConstruct的Service方法(或者在XML应用程序上下文中使用bean的onStartUp
属性)
例如,这个方法以前使用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>
答案 0 :(得分:1)
如HibernateDaoSupport class docs中所述,“如果传入SessionFactory,此类将创建自己的HibernateTemplate实例。默认情况下,HibernateTemplate上的'allowCreate'标志将为'true'。”这意味着在旧系统下,您的DAO可以按需打开会话,而不受任何实际控制。
当Spring管理SessionFactory时,它会安装SpringSessionContext作为Hibernate的CurrentSessionContext。现在,当您调用SessionFactory.getCurrentSession()
时,SpringSessionContext在Spring管理的ThreadLocal中查找会话,如果不存在则会失败。会话通常以两种方式之一打开并放置在那里:使用open-session-in-view模式对每个新请求执行此操作,并且启动事务也是如此。在您的情况下,您没有执行代码以响应请求,因此OSIV不在运行中,并且您显然也不在活动事务中。使方法具有事务性将解决您的问题。