Транзакция «ТРЕБУЕТСЯ» распространения весной - PullRequest
0 голосов
/ 14 февраля 2012

Я новичок в Spring и не могу выполнить транзакцию в режиме «ТРЕБУЕТСЯ».

Вот пример:

@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 (важные биты):

<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(...) не откатывается (или, возможно, это так, нобазы данных конечно нет).Кто-нибудь знает почему?

Ответы [ 2 ]

3 голосов
/ 14 февраля 2012

Если исключение возникает в bar.simpleMethod(), foo.save(...) не откатывается

И так не должно быть - вы обернули аннотации транзакций индивидуально вокруг Bar.simpleMethod и Foo.save, и поэтому они будут выполняться как две отдельные транзакции. Если Bar.simpleMethod терпит неудачу, он откатывает свою собственную транзакцию, но транзакция Foo.save уже зафиксирована. Там нет ни одной транзакции, охватывающей оба.

Вам необходимо заключить две операции в метод, который выполняет обе операции в одной транзакции. Это лучше всего сделать, добавив дополнительный компонент, который вызывается контроллером. Этот метод будет помечен @Transactional и выполняет Bar.simpleMethod и Foo.save. @Transactional аннотации Bar.simpleMethod и Foo.save будут включены в одну общую транзакцию.

2 голосов
/ 14 февраля 2012

У вас есть две независимые транзакции здесь.Первый зафиксирован, второй откатывается при исключении.Ничего удивительного здесь на самом деле.Чтобы эти два вызова участвовали в одной и той же транзакции, вы должны поместить их в один метод, помеченный @Transactional.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...