我正在使用Hibernate 3.6.9与Atomikos和Spring 3.1。在阅读Where does the @Transactional annotation belong?之后,我已经从所有DAO中删除了@Transactional注释,并且我只将它们留在了服务上。在我收到的任何dao db操作中删除这些注释后
org.hibernate.HibernateException: Unable to locate current JTA transaction
我的配置:
<tx:annotation-driven transaction-manager="jtaTransactionManager" />
<!-- Configure the Spring framework to use JTA transactions from Atomikos -->
<bean id="jtaTransactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager" ref="atomikosTransactionManager" />
<property name="userTransaction" ref="atomikosUserTransaction" />
</bean>
<!-- Construct Atomikos UserTransactionManager, needed to configure Spring -->
<bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"
init-method="init" destroy-method="close">
<!-- when close is called, should we force transactions to terminate or
not? -->
<property name="forceShutdown" value="false" />
</bean>
<!-- Also use Atomikos UserTransactionImp, needed to configure Spring -->
<bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
<property name="transactionTimeout" value="300" />
</bean>
会话工厂属性:
<prop key="hibernate.connection.isolation">3</prop>
<prop key="hibernate.current_session_context_class">jta</prop>
<prop key="hibernate.transaction.factory_class">com.atomikos.icatch.jta.hibernate3.AtomikosJTATransactionFactory
</prop>
<prop key="hibernate.transaction.manager_lookup_class">com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup
</prop>
我应该如何管理DAO的交易,以及如何在服务之外使用DAO?解决此问题的唯一方法是在任何使用daos的层中手动启动事务(Transactional with propagation requires_new)?但是当使用Transactional与DAO时,我遇到了延迟初始化异常的问题(事务在表示层之前关闭 - 尝试初始化实体字段)。
编辑:
当spring mvc的控制器可以直接访问DAO时,我应该如何管理事务?控制器应该是交易性的吗?
我的问题也出现在登录过程中,因为Spring安全性使用dao(没有@Transactional)所以没有层启动事务?
将@Transactional添加到例如spring security使用的daos解决了这个问题 - &gt;当有@Transactional时一切正常,但没有这个注释就无法使用db。但是将@Transactional添加到某些DAO会带来问题,因为当spring mvc想要显示某些数据时,会出现延迟初始化异常,然后只能在dao中手动Hibernate.initialize(因为最后@Transactional在表示层之前关闭了事务!)。
答案 0 :(得分:1)
IMO,您应该初始化DAO中对象的那些字段,这些字段稍后在表示层中需要。
如果急切地初始化这些对象对你来说有些“脏”,你应该引入新的表示层特定类(视图模型),这些类由服务层映射到(如果需要,它仍然有一个打开的事务来读取)。
由于我没有Java背景,我不知道“spring security”是否需要访问数据库。如果是这样,您必须在相应的服务层上添加这些事务属性,如您已经发现的那样。但是,我认为你不一定要在DAO方法中放置事务属性,这通常是一个层次到深层次。
答案 1 :(得分:0)
不,错误告诉您配置JTA事务管理器:
选择最适合您情况的那个。
这个Hibernate论坛问题可能也是相关的:
https://forum.hibernate.org/viewtopic.php?p=2430788
控制器不是交易性的。您已将它们放在正确的位置 - 它们属于服务。
OpenSessionInView可能是您的解决方案:
http://springtips.blogspot.com/2007/07/open-session-in-view.html
或者它可能不会:
Why is Hibernate Open Session in View considered a bad practice?