我目前正在编写一个spring-webmvc应用程序,几天前,我的第一个问题是我不知道如何使用Hibernate和Spring进行交易。现在一切正常,一个事务管理器上线了,我可以成功地处理事务。
这是我基于Java的Spring配置的一部分:
@Configuration
@ComponentScan(basePackages = { "de.macomp.maipds" })
@EnableTransactionManagement
public class MainConfigLib {
...
@Bean
public HibernateTransactionManager transactionManager() {
HibernateTransactionManager manager = new HibernateTransactionManager(sessionFactory());
return manager;
}
}
因此,当我想让我的服务层或dao层中的方法在事务中运行时,我只需用@Transactional对其进行注释,一切正常。我的问题是,当我不想让服务方法在事务内运行时,会出现以下错误:
org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
发生这种情况的代码如下所示:
...
@Override
public Publisher findByName(String name) {
Session session = this.sessionFactory.getCurrentSession();
//bam!
...
我能以某种方式“强制”我的环境给我一个“非事务性”会话吗?!我的DAO中sessionFactory的transactionManager属性为空。
将@Transactional添加到“findByName”可以解决问题,但对于此方法,不需要任何事务...
有什么想法吗?
需要事务,可以将此方法标记为只读
@Transactional(readOnly = true)
public Publisher findByName(String name) {
...
}
从Spring留档:
只读状态:只读事务不会修改任何数据。在某些情况下(例如使用Hibernate时),只读事务可能是一种有用的优化。
来自JBoss Wiki
许多应用程序开发人员认为他们可以在事务之外与数据库对话。这显然是不可能的;在数据库事务之外,不能向数据库发送任何SQL语句。术语非事务性数据访问意味着没有明确的事务边界,没有系统事务,并且数据访问的行为是自动提交模式的行为。这并不意味着不涉及物理数据库事务。
更多:
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref bean="mySessionFactory"/>
</property>
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
添加上述定义,并用@Transactional注释标记服务或dao类。