5

取引に少し問題があります。Spring 3.1.1.RELEASE、Spring Data 1.0.3.RELEASE JPA with 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 extends 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何らかの形でこのトランザクションを提供するというものです。Spring 構成で、アプリケーションではトランザクションが機能せず、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
4

1 に答える 1

2

私はまったく同じ問題を抱えていました。<tx:annotation-driven/>また、私の Web 構成 (spring-servlet.xmlの代わりに) にタグを追加するソリューションを読んで、applicationContext.xml私のために働きました。

しかし、私はそれが良い解決策だとは思わなかったので、なぜそれが起こっているのかを理解しようとしました...

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

解決策(良いもの):より良い(より具体的な)component-scan構成spring-servlet.xml

于 2012-06-03T10:04:07.933 に答える