我对交易中的交易有疑问。对于背景,我有一个School实体对象,其中有一组学生实体对象映射到它。我正在使用Spring Data JPA来处理所有的crud操作。我有一个SchoolManagementService类,它在类级别设置了@Transactional(readonly = true),对于我使用@Transactional的所有更新方法。 在我的SchoolManagementService类中,我有一个方法deleteStudents(List),我将其标记为@Transactional。在这个方法中,我一次又一次地调用StudentsRepository.delete(studentId)。我想确保是否有任何删除失败,然后事务应回滚该已检查的异常。我试图用我的spring junit测试用例测试这个(我没有使用默认的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)
}
使用此测试用例,它将删除所有记录,但最后一个记录。理想情况下,它应该回滚,不应删除任何条目。
这是我的sprin设置文件,包含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,并且它调用了几个Spring Data JPA存储库的@Transactional方法,那么如果我遇到任何Runtime异常,那么所有的事务都应该回滚。 我甚至尝试简单地创建一个testcase方法,如下所示:
@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。我认为这个testcase方法的@Transactional会在这里创建一个新事务,而StudentRepository中的所有事务删除方法都将在同一个事务中运行。除非没有抛出运行时异常,否则不会提交任何学生数据。
请帮助我更好地理解交易,因为我是新手。我正在将Spring Data JPA与Oracle数据库一起使用。
提前致谢。
答案 0 :(得分:0)
我认为默认行为是(甚至认为你在测试类上没有它)
@TransactionConfiguration(defaultRollback = true)
所以当你的测试结束时它会执行回滚。因此,hibernate会话与数据库没有同步,也没有向数据库发出查询SQL。
你有两个可能性。指定
@TransactionConfiguration(defaultRollback = false)
或将实体经理注入您的考试并致电
@PersistenceContext
protected EntityManager em;
/**
* Simulates new transaction (empties Entity Manager cache).
*/
public void simulateNewTransaction() {
em.flush();
em.clear();
}
这将强制hibernate将所有查询发送到数据库。请注意,这将解决您删除非现有实体的问题,但它的行为与新交易完全不同,例如当你丢失外键时它不会抛出任何东西(这是可以预测的。
您可以使用它来检查em.find(class,id)返回的实体的内容,并检查关系映射,而无需提交事务。