Проблема с аннотациями @Transactional в Spring JPA

У меня есть сомнения, связанные с транзакциями внутри транзакций. В качестве фона у меня есть объект сущности School, с которым сопоставлен объект сущности Set of Student. Я использую Spring Data JPA, который заботится обо всех грубых операциях. У меня есть класс SchoolManagementService, в котором @Transactional (readonly = true) установлен на уровне класса, и для всех методов обновления я использую для них @Transactional. В моем классе SchoolManagementService у меня есть метод deleteStudents (List), который я пометил как @Transactional. В этом методе я снова и снова вызываю StudentsRepository.delete (studentId). Я хочу убедиться, что в случае сбоя какого-либо удаления транзакция должна откатиться для этого проверенного исключения. Я пытаюсь проверить это с помощью моего тестового примера spring junit (я не использую default rollback = true или @ rollback (true), потому что я хочу, чтобы это было отменено из-за некоторого исключения времени выполнения, с которым я сталкиваюсь в методе удаления репозитория.

@RunWith(SpringJUnit4ClassRunner.class)   
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class})   
@ContextConfiguration(locations = {"classpath:PPLRepository-context.xml"})
public class TestClass{


@Test
@Transactional
public void testDeleteStudents(){
StudentManagementService.delete(randomList)
}

в этом тестовом примере удаляются все записи, кроме последней. В идеале он должен откатиться и ни одна из записей не должна быть удалена.

Вот мой файл настроек сприна с конфигами TransactionMangaer

<bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init"
            destroy-method="close">
            <property name="forceShutdown" value="true" />
            <property name="startupTransactionService" value="true" />
            <property name="transactionTimeout" value="1000" />
        </bean>

        <bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp" />
        <!-- Configure the Spring framework to use JTA transactions from Atomikos -->
        <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
            <property name="transactionManager" ref="atomikosTransactionManager" />
            <property name="userTransaction" ref="atomikosUserTransaction" />
            <property name="transactionSynchronizationName" value="SYNCHRONIZATION_ON_ACTUAL_TRANSACTION" />
        </bean>

            <!-- EntityManager Factory that brings together the persistence unit, datasource, and JPA Vendor -->
            <bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="PPL_GMR">
                <property name="dataSource" ref="PPL_GMRDS"></property>
                <property name="persistenceUnitName" value="PPL_GMR"/>
                <property name="persistenceXmlLocation" value="classpath:META-INF/PPL-persistence.xml"/>
                <property name="jpaVendorAdapter" ref="PPL_GMRJPAVendorAdapter"/>
                    <property name="jpaPropertyMap">
                        <map>
                                    <entry key="hibernate.transaction.manager_lookup_class" value="com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup"/> 
                                    <entry key="hibernate.connection.release_mode" value="on_close"/>
                                    <entry key="hibernate.default_schema" value="${PPL.schema}"/>
                        </map>
                    </property>
</bean>

Может ли кто-нибудь подсказать, где я неправильно понимаю транзакции? Что бы я ни читал из API, у меня сложилось впечатление, что если какой-то метод является @Transactional на уровне обслуживания и если он вызывает несколько методов @Transactional репозиториев Spring Data JPA, тогда, если я обнаружу какое-либо исключение времени выполнения, все транзакции должны быть отменены . Я даже попытался просто создать тестовый метод, как показано ниже:

@Test
@Transactional
public void testDeleteStudents(){
StudentRepository.delete(1);
StudentRepository.delete(2);// 2 id is not present so I will get a runtime exception.
}

Несмотря на то, что в этом методе сохраняется @Rollback (true / false), этот метод удаляет id 1 Student из базы данных. Я думал, что @Transactional в этом тестовом методе создаст здесь новую транзакцию, и все методы транзакционного удаления из StudentRepository будут выполняться в одной транзакции. И никакие данные ученика не будут зафиксированы до тех пор, пока не будет сгенерировано исключение времени выполнения.

Пожалуйста, помогите мне лучше понять транзакции, поскольку я новичок в этом. Я использую Spring Data JPA с базой данных Oracle.

Заранее спасибо.


person Gaurav    schedule 22.01.2013    source источник
comment
Привет! Кто-нибудь может мне помочь с этим ... Эта проблема меня убивает ..   -  person Gaurav    schedule 23.01.2013


Ответы (1)


Я думаю, что поведение по умолчанию (даже если у вас его нет в тестовом классе)

@TransactionConfiguration(defaultRollback = true)

поэтому он выполнит откат, когда ваш тест закончится. Следовательно, нет синхронизации сеанса гибернации с базой данных, и к базе данных не отправляются запросы SQL.

У вас есть две возможности. Либо укажите

@TransactionConfiguration(defaultRollback = false)

или введите диспетчер сущностей в свой тест и позвоните

@PersistenceContext
protected EntityManager em;

/**
 * Simulates new transaction (empties Entity Manager cache).
 */
public void simulateNewTransaction() {
    em.flush();
    em.clear();
}

Это заставит спящий режим отправлять все запросы в базу данных. Обратите внимание, что это решит вашу проблему с удалением несуществующего объекта, но оно не будет вести себя точно так же, как новая транзакция, например когда у вас отсутствует внешний ключ, он ничего не бросает (это предсказуемо.

Вы можете использовать это для проверки содержимого объекта, возвращаемого em.find (class, id), и проверки вашего реляционного сопоставления без необходимости фиксировать транзакцию.

person František Hartman    schedule 05.02.2013