2013-01-22 65 views
1

我对于事务中的事务有疑问。对于背景,我有一个School实体对象,其中有一组学生实体对象映射到它。我正在使用Spring Data JPA来处理所有的粗暴操作。我有一个SchoolManagementService类,它在类级别设置了@Transactional(readonly = true),并为所有更新方法使用了@Transactional。 在我的SchoolManagementService类中,我有一个我标记为@Transactional的方法deleteStudents(List)。在这种方法中,我一次又一次地调用StudentsRepository.delete(studentId)。我想确保如果任何删除失败,那么事务应该回滚该检查的异常。我想用我的spring junit测试用例(我没有使用默认的rollback = true或@ rollback(true))来测试这个,因为我希望这个回滚是因为我在存储库删除方法中遇到了一些运行时异常。Spring在@Transactional注解中的问题JPA

@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 CONFIGS文件

<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方法,那么如果遇到任何运行时异常,则应回滚所有事务。 我甚至想简单的创建如下的测试用例方法:

这种方法保持@Rollback(真/假)的
@Test 
@Transactional 
public void testDeleteStudents(){ 
StudentRepository.delete(1); 
StudentRepository.delete(2);// 2 id is not present so I will get a runtime exception. 
} 

Inspite,这种方法从数据库中删除ID 1学生。我认为这个testcase方法中的@Transactional将在这里创建一个新的事务,并且来自StudentRepository的所有事务性删除方法都将在同一个事务中运行。除非抛出运行时异常,否则不会提交学生数据。

请帮助我更好地理解交易,因为我是新手。我正在使用Spring数据JPA和Oracle数据库。

在此先感谢。

+0

嗨,有人能帮我解决这个问题吗......这个问题正在让我失望.. – Gaurav

回答

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(); 
} 

这将迫使休眠所有查询发送到数据库。请注意,这将解决您的问题,即删除不存在的实体,但它的行为与新交易完全不同。当你缺少外键时它不会抛出任何东西(这是可以预测的)

你可以用它来检查em.find(class,id)返回的实体的内容,并检查你的关系映射,而不需要提交交易