Spring JPA中的@Transactional注释问题

Spring JPA中的@Transactional注释问题,spring,jpa,junit4,spring-transactions,transactional,Spring,Jpa,Junit4,Spring Transactions,Transactional,我对交易中的交易有疑问。作为背景,我有一个学校实体对象,它有一组映射到它的学生实体对象。我使用的是SpringDataJPA,它负责所有crud操作。我有一个SchoolManagementService类,该类在类级别设置了@Transactional(readonly=true),对于所有更新方法,我都在它们上面使用@Transactional。 在我的SchoolManagementService课程中,我有一个方法deleteStudents(List),我将其标记为@Transacti

我对交易中的交易有疑问。作为背景,我有一个学校实体对象,它有一组映射到它的学生实体对象。我使用的是SpringDataJPA,它负责所有crud操作。我有一个SchoolManagementService类,该类在类级别设置了@Transactional(readonly=true),对于所有更新方法,我都在它们上面使用@Transactional。 在我的SchoolManagementService课程中,我有一个方法deleteStudents(List),我将其标记为@Transactional。在这个方法中,我一次又一次地调用StudentsRepository.delete(studentId)。我想确保,如果任何删除失败,那么事务应该回滚该已检查异常。我试图用我的SpringJUnit测试用例来测试这一点(我没有使用默认的rollback=true)or@rollback(true),因为我希望回滚它,因为我在repository 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)
}
            <!-- 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>
在这个测试用例中,它将删除除最后一条记录之外的所有记录。理想情况下,它应该回滚,并且不应该删除任何条目

            <!-- 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>
这是我的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>
尽管保持@Rollback(真/假)在这个方法中,这个方法从数据库中删除id为1的Student。我认为这个testcase方法中的@Transactional将在这里创建一个新的事务,StudentRepository中的所有事务删除方法都将在同一个事务中运行。并且,除非没有引发运行时异常,否则不会提交学生数据

            <!-- 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>
请帮助我更好地理解事务,因为我是新手。我正在使用SpringDataJPA和Oracle数据库

            <!-- 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>

提前感谢。

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

            <!-- 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>
因此,当测试结束时,它将执行回滚。因此,hibernate会话不会与数据库同步,也不会向数据库发出SQL查询

            <!-- 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>
您有两种可能性。请指定

            <!-- 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>
@TransactionConfiguration(defaultRollback = false)
或者将实体管理器插入到测试和调用中

            <!-- 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>
@PersistenceContext
protected EntityManager em;

/**
 * Simulates new transaction (empties Entity Manager cache).
 */
public void simulateNewTransaction() {
    em.flush();
    em.clear();
}
这将迫使hibernate将所有查询发送到数据库。请注意,这将解决您删除不存在的实体的问题,但它的行为与新事务不同,例如,当您缺少外键时,它不会抛出任何东西(这是可预测的)

            <!-- 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>

您可以使用它来检查em.find(class,id)返回的实体的内容,并检查您的关系映射,而无需提交事务。

Hi,有人能帮我解决这个问题吗……这个问题快把我累死了。。
            <!-- 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>