Кажется, существует связь между наличием аннотации @Transactional в тесте Spring JUnit и каскадным отображением при сохранении / объединении сущности JPA2.
На данный момент у меня нет конфигурации, но, может быть, это кому-то здесь звонит?
Допустим простой случай объектов JPA на трех уровнях: объект A ссылается на объект класса B, а этот экземпляр класса B ссылается на экземпляр класса C.
A -> B -> C
Класс A выполняет каскадирование ALL для B. И B выполняет каскадирование ALL для C. И в классе C есть метод прослушивания событий, аннотированный @PrePersist и @PreUpdate. Он регистрирует сообщение, чтобы доказать, что каскад был сделан там.
Теперь измените сущность C каким-либо образом и попросите менеджера сущностей объединить или сохранить экземпляр A. Логически сущность C в конечном итоге также будет сохранена или объединена. Из-за каскадирования было установлено значение ALL от класса A до B до C.
Когда модульный тест Spring не аннотируется @Transactional, сообщение журнала из метода прослушивателя событий класса C печатает свое сообщение. OK.
Но если для указано с аннотацией @Transactional, сообщение вообще не печатается. И действительно, ничего не было передано в базу данных для класса C. Только для класса A. Следовательно, я пришел к выводу, что каскадирование не перешло из A в C.
Удаление аннотации устраняет проблему.
Кто-нибудь знает? :-) Логически я бы подумал, что транзакции и каскадирование - это две совершенно разные вещи.
Типичная конфигурация тестового набора:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/test-beans.xml")
@TransactionConfiguration
@Transactional
public class MyUnitTest {
...
@Test
public void testSomething() {}
...
}
Извлечение конфигурационного файла Spring xml - ничего особенного, я думаю ...
<context:annotation-config />
<tx:annotation-driven transaction-manager="transactionManager" />
<context:component-scan base-package="com.foo.bar" />
<bean id="jpaTemplate" class="org.springframework.orm.jpa.JpaTemplate">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation" value="/META-INF/persistence.xml"/>
<property name="persistenceUnitName" value="bar" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
Извлечение из файла persistence.xml
<persistence-unit name="bar" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" />
<property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/bar" />
<property name="hibernate.connection.username" value="bar" />
<property name="hibernate.connection.password" value="pwd" />
<property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/>
<property name="hibernate.hbm2ddl.auto" value="create"/>
<property name="dialect" value="org.hibernate.dialect.MySQLDialect" />
</properties>
</persistence-unit>
Библиотека
- Spring 3.0.6 ORM / CONTEXT / TEST
- Hibernate 3.6.7.Final
- JUnit 4.9
- JPA2