当前位置: 首页 > 知识库问答 >
问题:

Spring JPA中的@Transactional注释问题

籍兴文
2023-03-14

我有一个与交易中的交易有关的疑问。作为背景,我有一个School实体对象,它有一组映射到它的Students实体对象。我使用的是Spring Data JPA,它负责所有的crud操作。我有一个SchoolManagementService类,它在类级别设置了@transactional(readonly=true),对于所有更新方法,我都在它们上面使用@transactional。在我的SchoolManagementService类中,我有一个方法deleteStudents(List),我将它标记为@Transactional。在这个方法中,我反复调用StudentsRepository.delete(studentId)。我想确保如果任何删除失败,那么事务应该回滚该检查的异常。我试图用我的spring junit测试用例来测试这个问题(我没有使用默认的rollback=true或@rollback(true),因为我希望这个问题被回滚,因为我在存储库delete方法中遇到了一些运行时异常。

@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)
}

在这个testcase中,它删除了除最后一个记录之外的所有记录。理想情况下,它应该回滚,任何条目都不应该被删除。

这是带有TransactionMangaer配置的sprin设置文件

<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方法,那么如果我遇到任何运行时异常,那么所有事务都应该回滚。我甚至尝试简单地创建一个testcase方法,如下所示:

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

共有1个答案

闾丘文昌
2023-03-14

我认为默认的行为是(即使在测试类中没有)

@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)返回的entity的内容,并检查您的关系映射,而不需要提交事务。

 类似资料:
  • 问题内容: 你应该将放置在类和/或它们的方法中,还是更好地注释使用DAO对象调用的Service类?还是对两个“层”都进行注释是否有意义? 问题答案: 我认为交易属于服务层。这是了解工作单元和用例的人。如果你将多个DAO注入到一个服务中,而这些DAO需要在单个事务中一起工作,那么这是正确的答案。

  • 问题内容: 我的@Transactionnal注释似乎被忽略了。我对Spring容器的初始化没有任何错误。看来我的方法尚未被Spring TX框架代理。在执行服务的方法期间,JDBCTemplate会引发预期的RuntimeException。问题在于JDBC连接没有回滚,并且更改保持不变。stacktrace没有显示应该包装我的服务方法的代理的任何迹象。 编辑:添加了控制器的代码 编辑2:添加了

  • 问题内容: 我已成功将此注释用于Dao类。回滚适用于测试。 但是现在我需要回滚真实代码,而不仅仅是测试。有用于测试的特殊注释。但是哪些注释适用于非测试代码?对我来说这是一个大问题。我已经花了一天的时间。官方文档不符合我的需求。 employeeDao is 这是一个注释可以很好地运行的测试: HibernateDaoBeans.xml 是的,我回滚了交易。我刚刚为服务添加了BEAN …,然后注释@

  • 问题内容: 你应该将放置在DAO类和/或它们的方法中,还是更好地注释使用DAO对象调用的类?还是对两个“层”都进行注释是否有意义? 问题答案: 我认为交易属于服务层。这是了解工作单元和用例的人。如果您将多个DAO注入到一个服务中,而这些DAO需要在单个事务中一起工作,那么这是正确的答案。

  • 我开始制作一个简单的spring boot应用程序。 我的第一步是利用Spring JDBC支持,使用默认的H2内存数据库。对于示例数据,我在src/main/resources中有schema.sql和data.sql。 所以当spring启动时,它也会执行这两个脚本并填充H2数据库,我可以通过H2控制台访问它。