交易“必需"Spring中的传播 [英] Transaction "REQUIRED" propagation in Spring
问题描述
我是 Spring 的新手,无法在必需"模式下进行事务传播.
I'm new to Spring and I'm not able to make the transaction propagation in "REQUIRED" mode.
这是一个例子:
@Controller
public class ExampleController
{
@Autowired
Foo foo;
@Autowired
Bar bar;
@RequestMapping(value = "/example")
public String submitForm(Model model) throws Exception
{
User user = new User("Joe", "Bloggs");
user = foo.save(user);
bar.simpleMethod(user);
return "success";
}
}
<小时>
@Repository
public class Foo
{
// A JPA repository
private EntityManager em;
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
public User save(User user)
{
return this.em.merge(user);
}
@PersistenceContext
void setEntityManager(EntityManager entityManager)
{
this.em = entityManager;
}
}
<小时>
public class Bar
{
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
public void simpleMethod(User user)
{
// Do something...
}
}
applicationContext.xml(重要部分):
The applicationContext.xml (important bits):
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
<context:property-placeholder location="/WEB-INF/jdbc.properties" />
<bean id="dataSource" class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy">
<constructor-arg>
<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${db.driverClassName}" />
<property name="url" value="${db.url}" />
<property name="username" value="${db.username}" />
<property name="password" value="${db.password}" />
</bean>
</constructor-arg>
</bean>
<bean id="jpaAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect" />
<property name="showSql" value="${db.showSql}" />
<property name="generateDdl" value="${db.generateDdl}" />
</bean>
<!-- enabling annotation driven configuration /-->
<context:annotation-config />
<context:component-scan base-package="my.package" />
<!-- Instructs the container to look for beans with @Transactional and decorate them -->
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />
<!-- FactoryBean that creates the EntityManagerFactory -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="jpaVendorAdapter" ref="jpaAdapter" />
<property name="jpaProperties">
<props>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
<property name="dataSource" ref="dataSource" />
</bean>
<!-- A transaction manager for working with JPA EntityManagerFactories -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
</beans>
如果 bar.simpleMethod()
中出现异常,foo.save(...)
不会回滚(或者可能是,但数据库是当然不是).有谁知道为什么?
If an exception occours in bar.simpleMethod()
, foo.save(...)
is not rolled back (or maybe it is, but the database is certainly not). Does anyone know why?
推荐答案
如果
bar.simpleMethod()
发生异常,foo.save(...)
不会回滚
两者都不应该 - 您已经将事务注释单独包装在 Bar.simpleMethod
和 Foo.save
周围,因此这些将作为两个单独的事务执行.如果 Bar.simpleMethod
失败,它会回滚自己的事务,但 Foo.save
的事务已经提交.没有涵盖两者的单一交易.
And neither it should be - you've wrapped your transaction annotations individually around Bar.simpleMethod
and Foo.save
, and so these will be performed as two separate transactions. If Bar.simpleMethod
fails, it rolls back its own transaction, but Foo.save
's transaction has already been committed. There's no single transaction covering both.
您需要将这两个操作封装在一个方法中,该方法在单个事务中执行这两个操作.这最好通过引入一个由控制器调用的额外组件来完成.此方法将使用 @Transactional
进行注释,并执行 Bar.simpleMethod
和 Foo.save
.Bar.simpleMethod
和 Foo.save
上的 @Transactional
注释将成为同一整体事务的一部分.
You need to encapsulate the two operations within a method that performs both operations in a single transaction. This is best done by introducing an extra component, which is invoked by the controller. This method would be annotated with @Transactional
, and performs Bar.simpleMethod
and Foo.save
. The @Transactional
annotations on Bar.simpleMethod
and Foo.save
will be made part of the same overall transaction.
这篇关于交易“必需"Spring中的传播的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!