[英]Spring, JPA transactions works only in JUnit test but not in application
我的交易有點問題。 我使用Spring 3.1.1.RELEASE,Spring Data 1.0.3.RELEASE JPA和Hibernate提供程序。 當我開始一個junit測試時,使用@Transactional
注釋的方法看起來很好但是當我啟動一個完整的應用程序時,沒有錯誤但是事務不起作用。 這是我的配置和示例代碼:
applicationContext.xml中
<context:annotation-config />
<context:component-scan base-package="com.sheedo.upload" />
<jpa:repositories base-package="com.sheedo.upload.repository" />
<tx:annotation-driven transaction-manager="transactionManager" />
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath*:messages/*.properties</value>
<value>classpath*:*.properties</value>
</list>
</property>
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="persistenceUnit" />
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="dataSource" class="com.mysql.jdbc.jdbc2.optional.MysqlDataSource">
<property name="url" value="${jdbc.url}" />
<property name="user" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
persistence.xml中
<persistence-unit name="persistenceUnit" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLInnoDBDialect" />
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy" />
<property name="hibernate.connection.charSet" value="UTF-8" />
<property name="hibernate.show_sql" value="true" />
</properties>
</persistence-unit>
UserRepository.java
public interface UserRepository擴展CrudRepository <User,Long> {}
UserServiceImpl.java
@Service("userService")
public class UserServiceImpl implements UserService {
@Autowired
private UserRepository userRepository;
@Override
@Transactional
public void addUser(String name, String surname) {
User u = new User(name, surname);
userRepository.save(u);
throw new RuntimeException(); // to invoke a rollback
}
}
UserServiceTest.java
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:/META-INF/spring/root-context.xml" })
public class UserServiceTest {
Logger log = LoggerFactory.getLogger(getClass());
@Autowired
private UserService userService;
@Test
public void testUserAdd() {
userService.addUser("John", "Doe");
}
}
在這種JUnit測試的情況下,雖然服務方法使用@Transactional
注釋,但事務不起作用。 當我將這個注釋添加到testUserAdd()
方法時,我在控制台中得到了這個:
2012-05-17 11:17:54,208 INFO [org.springframework.test.context.transaction.TransactionalTestExecutionListener] - Rolled back transaction after test execution for test context [[TestContext@23ae2a testClass = UserRepositoryTest, testInstance = com.sheedo.upload.repository.UserRepositoryTest@7f52c1, testMethod = testUserAdd@UserRepositoryTest, testException = java.lang.RuntimeException, mergedContextConfiguration = [MergedContextConfiguration@111fd28 testClass = UserRepositoryTest, locations = '{classpath:/META-INF/spring/root-context.xml}', classes = '{}', activeProfiles = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader']]]
這是正確的,我想。 那么,@ @Transactional
注釋怎么可能只在Junit測試類中起作用,而在其他的spring bean中卻不行?
我的理論是SpringJUnit4ClassRunner
以某種方式提供了這個事務。 我的彈簧配置中有什么問題導致交易在我的應用程序中不起作用但僅在Junit測試類中有效嗎? appContext中缺少什么?
編輯:日志:
2012-05-17 12:46:10,770 DEBUG [org.springframework.orm.jpa.JpaTransactionManager] - Creating new transaction with name [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
2012-05-17 12:46:10,770 DEBUG [org.springframework.orm.jpa.JpaTransactionManager] - Opened new EntityManager [org.hibernate.ejb.EntityManagerImpl@e4080] for JPA transaction
2012-05-17 12:46:10,979 DEBUG [org.springframework.orm.jpa.JpaTransactionManager] - Not exposing JPA transaction [org.hibernate.ejb.EntityManagerImpl@e4080] as JDBC transaction because JpaDialect [org.springframework.orm.jpa.DefaultJpaDialect@1f87491] does not support JDBC Connection retrieval
Hibernate: insert into user (name, surname) values (?, ?)
2012-05-17 12:46:11,062 DEBUG [org.springframework.orm.jpa.JpaTransactionManager] - Initiating transaction commit
2012-05-17 12:46:11,062 DEBUG [org.springframework.orm.jpa.JpaTransactionManager] - Committing JPA transaction on EntityManager [org.hibernate.ejb.EntityManagerImpl@e4080]
2012-05-17 12:46:11,142 DEBUG [org.springframework.orm.jpa.JpaTransactionManager] - Closing JPA EntityManager [org.hibernate.ejb.EntityManagerImpl@e4080] after transaction
2012-05-17 12:46:11,142 DEBUG [org.springframework.orm.jpa.EntityManagerFactoryUtils] - Closing JPA EntityManager
我有完全相同的問題。 另外,閱讀在我的Web配置中添加<tx:annotation-driven/>
標記的解決方案( spring-servlet.xml
,而不是applicationContext.xml
),並為我工作。
但我不認為這是一個很好的解決方案,所以我試着理解為什么會這樣......
好吧,事實證明我在spring-servlet.xml
中的<context:component-scan>
標簽在其掃描中也包含了@Service
類( base-package
規范過於籠統)。 這很奇怪,因為我有一個include-filter
來引用@Controller
注釋......但無論如何,似乎Web層的應用程序上下文是創建@Service
實例的應用程序上下文而不是為applicationContext創建的applicationContext.xml
程序上下文。 applicationContext.xml
這是定義業務層的那個 - 並且由於前者沒有啟用事務性...我沒有任何事務。
解決方案(很好): spring-servlet.xml
更好(更具體)的component-scan
配置
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.