2012-05-17 15 views
5

トランザクションには少し問題があります。 Spring 3.1.1.RELEASE、Spring Data 1.0.3.RELEASE JPAをHibernateプロバイダとともに使用します。私がjunitテストを開始するときに、@Transactionalと注釈を付けたメソッドはどこにあるかは分かりますが、アプリケーション全体を起動するとエラーは発生しませんが、トランザクションは機能しません。 は、ここに私の構成やサンプルコードです:Spring、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はJUnitテストのこの場合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"); 
    } 

} 

を拡張し、トランザクションがイベントを動作しませんサービス方法には@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テストクラスでしか動作しませんが、他のどのクラスでも動作しない可能性はありますか?

私の理論では、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 [[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

ではどのように取引が「動作しない」ことを診断するのですか? –

+0

UserServiceでこのトランザクションメソッドをデバッグすると、メソッドが例外で終了しても、 "userRepository.save(user)"の後にエンティティをデータベースに保存しました。そして、トランザクションが開始されたコンソールにはログインしていません。 –

+0

"org.springframework.transaction"ロガーを有効にします。同じものを投稿してください。これはさらなる分析に役立ちます。 –

答えて

2

私は正確に同じ問題を抱えていました。また、の代わりにタグをWebコンフィギュレーション(spring-servlet.xml)に追加して、私のために働いてください。

しかし、私は良い解決策と考えていなかったので、私は

...それが起こった理由を理解しようとしただけでなく、それは私が私のspring-servlet.xmlに持っていた<context:component-scan>タグは@Service含めてもいたことが判明クラスのスキャン(base-packageの仕様があまりにも一般的でした)。これはという部分が@Controller注釈を参照しているために奇妙でした...とにかく、Webレイヤのアプリケーションコンテキストは、applicationContext.xmlのために作成されたアプリケーションコンテキストの代わりに@Serviceインスタンスを作成したものでした。ビジネス層を定義するものです。前者はトランザクション性を有効にしていないため、トランザクションはありませんでした。

ソリューション(良いもの):より良い(より具体的な)component-scan設定spring-servlet.xml

+0

同じ問題がありました。インクルードフィルタが定義されていても、Webアプリケーションコンテキストが間違ったBeanをロードしていましたそして、明らかに、Webアプリのコンテキストにはありませんでした。 spring-servlet.xml(またはWebレイヤapplicationcontextという名前のもの)がロードされ、ログ内でこのステートメントがロードされるタイミングをログで調べます: "Bean factory for WebApplicationContext" - これらのBeanを検索して、Webアプリケーションコンテキストが読み込まれました。 –

関連する問題