2014-02-22 67 views
1

Hibernate在我的一個測試方法中拋出了javax.persistence.TransactionRequiredException。但是,根據日誌,正在進行的交易(由Spring創建)。有沒有人知道我可能會錯過什麼?Hibernate在Spring事務中拋出TransactionRequiredException

查看日誌:

INFO org.springframework.test.context.transaction.TransactionalTestExecutionListener - Began transaction (1) for test context [[email protected] testClass = FooTest, testInstance = [email protected], testMethod = [email protected], testException = [null], mergedContextConfiguration = [[email protected] testClass = FooTest, locations = '{classpath:/appContext.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]]; transaction manager [o[email protected]1f05562b]; rollback [true] 
INFO com.example.FooTest - Test started. 
INFO org.springframework.test.context.transaction.TransactionalTestExecutionListener - Rolled back transaction after test execution for test context [[email protected] testClass = FooTest, testInstance = [email protected], testMethod = [email protected], testException = javax.persistence.TransactionRequiredException: Executing an update/delete query, mergedContextConfiguration = [[email protected] testClass = FooTest, locations = '{classpath:/appContext.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]] 

我的測試類是:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration("/appContext.xml") 
@Transactional 
public class FooTest { 

    private static final Logger logger = LoggerFactory.getLogger(FooTest.class); 

    @PersistenceContext 
    private EntityManager em; 

    @Test 
    public void test() { 
     logger.info("Test started."); 
     em.createQuery("delete from Foo").executeUpdate(); 
     logger.info("Test finished."); 
    } 

} 

我appContext.xml是:

<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:tx="http://www.springframework.org/schema/tx" 
    xmlns:jdbc="http://www.springframework.org/schema/jdbc" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
      http://www.springframework.org/schema/beans/spring-beans.xsd 
      http://www.springframework.org/schema/tx 
      http://www.springframework.org/schema/tx/spring-tx.xsd 
      http://www.springframework.org/schema/jdbc 
      http://www.springframework.org/schema/jdbc/spring-jdbc.xsd"> 

    <bean id="embeddedEmf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
    <property name="dataSource" ref="embeddedDataSource"/> 
    <property name="persistenceUnitName" value="Foo" /> 
    </bean> 

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
    <property name="dataSource" ref="embeddedDataSource"/> 
    </bean> 

    <tx:annotation-driven transaction-manager="transactionManager"/> 

    <jdbc:embedded-database id="embeddedDataSource"> 
    <jdbc:script location="classpath:schema.sql" encoding="UTF-8"/> 
    <jdbc:script location="classpath:test-data.sql" encoding="UTF-8"/> 
    </jdbc:embedded-database> 

</beans> 

我的META-INF/persistence.xml中是相當直截了當:

<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" 
    version="2.0"> 
    <persistence-unit name="Foo"> 

    <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider> 

    <class>com.example.Foo</class> 

    </persistence-unit> 
</persistence> 

最後,堆棧跟蹤(過濾):

javax.persistence.TransactionRequiredException: Executing an update/delete query 
    at org.hibernate.jpa.spi.AbstractQueryImpl.executeUpdate(AbstractQueryImpl.java:71) 
    at com.example.FooTest.test(FooTest.java:27) 
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74) 
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83) 
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:232) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:89) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) 
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) 
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71) 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:175) 
+2

使用屬於您的技術的事務管理器。您正在使用JPA,因此請使用'JpaTransactionManager'而不是'DataSourceTransactionManager'。 –

+0

非常感謝。就是這樣。 –

+0

@ M.Deinum我在應用程序中同時使用了SpringJDBC和JPA。使用JPATransactionManager會在我使用SpringJDBC的地方給出錯誤,並且在我使用JPA的地方使用DataSourceTransactionManager給出錯誤。任何方式呢? – Dojo

回答

0

我正在使用錯誤的事務管理器。解決的辦法是更換:

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
    <property name="dataSource" ref="embeddedDataSource"/> 
</bean> 

通過

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 
    <property name="dataSource" ref="embeddedDataSource"/> 
</bean> 

非常感謝M. Deinum爲他的評論。如果他把它作爲答案發布,我會接受它。

0

我同意,你應該使用JpaTransactionManager接口。我也相信你需要標記的方法事務:

@Transactional 
public void test() { 

您可以通過硬調試它編碼的交易開始並在測試提交。它看起來像指向em.createQuery ....的異常(因此,如果您想進一步診斷,那麼硬編碼該事務)。

希望對我有所幫助:)

+0

如果您未指定任何其他TestExecutionListener,則默認情況下,測試方法是事務性的。所以不需要標記'@ Transactional'。 –

相關問題