我正在尝试使用@Transactional
Spring framework
的方法打开方法的多个交易
由于某种原因,它会抛出java.lang.IllegalStateException : Transaction already active
我的方法
@Transactional
Public void foo(Entity e){
entityManager.merge(e);
entityManager.getTransaction().begin();
entityManager.getTransaction().commit();
}
知道如何在不收到错误的情况下打开多个交易吗?
答案 0 :(得分:2)
我认为你可能会混淆Spring @Transactional
注释的含义。当您使用该注释时,您要求Spring使用事务语义来丰富您的方法调用。
您可能需要查看TransactionAspectSupport类,更具体地说是方法invokeWithinTransaction,这是您的交易方法发生所有魔法的地方。
您将看到在调用代码之前,创建了一个新事务,然后执行了代码,之后,发生了提交或回滚。换句话说,Spring的方面控制着你的交易。
所有这些魔法需要一些配置才能实现:你需要确保Spring找到你的@Transactional
方法并丰富它们。为此,您需要添加一段配置:
<tx:annotation-driven/>
当然,您需要定义可由事务方法使用的事务管理器。看来你正在使用JPA,所以JpaTransactionManager在这种情况下有意义:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="POSTGRESQL"/>
<property name="showSql" value="true"/>
</bean>
</property>
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect">
<property name="prepareConnection" value="true"/>
</bean>
</property>
<property name="persistenceUnitName" value="test-api"/>
<property name="packagesToScan">
<list>
<value>com.company.humanresources</value>
</list>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<constructor-arg name="emf" ref="entityManagerFactory"/>
</bean>
最后,如果您想获得当前交易所使用的实体经理的访问权限,您可以执行以下操作:
@PersistenceUnit(unitName = "test-api")
EntityManagerFactory emf;
@Transactional
public Department addDepartment(String name) {
EntityManager em = EntityManagerFactoryUtils.getTransactionalEntityManager(emf);
Department department = new Department();
department.setName(name);
em.persist(department);
return department;
});
Spring将再次控制事务方法的事务语义。您还必须考虑到默认的Spring行为仅适用于公共方法。