2012-05-17 39 views
5

我有一个交易小问题。我使用Spring 3.1.1.RELEASE,Spring Data 1.0.3.RELEASE JPA和Hibernate provider。当我开始JUnit测试其中一个方法标注了@Transactional似乎罚款,但是当我开始整个应用程序没有错误,但成交不工作。 这里是我的配置和示例代码:春天,JPA交易只能在JUnit测试而不是在应用

的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

公共interfa CE UserRepository扩展CrudRepository <用户,龙> {}

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 [[[email protected] testClass = UserRepositoryTest, testInstance = [email protected], testMethod = [email protected], testException = java.lang.RuntimeException, mergedContextConfiguration = [[email protected] 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 [or[email protected]] for JPA transaction 
2012-05-17 12:46:10,979 DEBUG [org.springframework.orm.jpa.JpaTransactionManager] - Not exposing JPA transaction [[email protected]] as JDBC transaction because JpaDialect [[email protected]] 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 [[email protected]] 
2012-05-17 12:46:11,142 DEBUG [org.springframework.orm.jpa.JpaTransactionManager] - Closing JPA EntityManager [[email protected]] after transaction 
2012-05-17 12:46:11,142 DEBUG [org.springframework.orm.jpa.EntityManagerFactoryUtils] - Closing JPA EntityManager 
+0

component-scan配置如何诊断的事务“不工作”? –

+0

当我在UserService中调试这个事务性方法时,即使该方法完成了异常,它会在“userRepository.save(user)”之后将实体保存到数据库中。我没有登录控制台该交易开始。 –

+0

启用“org.springframework.transaction”记录器。同样的。这将有助于进一步分析。 –

回答

2

我有完全相同的问题。此外,阅读在我的web配置中添加(spring-servlet.xml而不是applicationContext.xml)一<tx:annotation-driven/>标签的解决方案,并为我工作。

但我不认为这是一个很好的解决方案,所以我试图理解为什么这是怎么回事......

很好,事实证明,一个<context:component-scan>标签,我在我的spring-servlet.xml还包括@Service扫描中的类(base-package规范太笼统)。这很奇怪,因为我曾在一个地方提到include-filter@Controller注解......但无论如何,似乎是web层应用程序上下文是一个创建@Service实例,而对于applicationContext.xml创建的应用程序上下文,可呈现的是定义业务层的那个 - 并且因为前者没有启用事务性......我没有任何事务。

解决方案(好的):更好(更具体)在spring-servlet.xml

+0

有同样的问题。即使包含筛选器已定义,Web应用程序上下文也会加载错误的bean。显然,在web应用上下文中没有。当spring-servlet.xml(或者任何你命名的web层applicationcontext)加载时,检查你的日志,并在日志中查找这条语句:“WebApplicationContext的Bean工厂” - 你可以搜索这些bean来查看web应用程序上下文加载它。 –