在Spring JUnit测试中存在@Transactional注释与在持久化/合并JPA2实体时级联之间似乎存在联系。
我暂时没有手头的配置,但也许这会给这里的某个人敲响一声?
在三个级别上假设一个简单的JPA实体案例:实体A引用类B的实体,而类B的实例引用类C的实例。
A - > B - > ç
A类将ALL级联为B.并且B将ALL级联为C.而C类具有使用@PrePersist和@PreUpdate注释的事件侦听器方法。它会记录一条消息,以证明级联到达那里。
现在,以某种方式修改实体C并要求实体管理器合并或持久化A的实例。逻辑上,实体C最终将被持久化或合并。由于级联已设置为ALL,从A到B到C。
当Spring单元测试未使用@Transactional注释时,来自C类事件侦听器方法的日志消息将打印其消息。行。
但是当 使用@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>
库
答案 0 :(得分:0)
我实现了一个需要EntityManager的Query结果迭代器。我以为我可以从jpaTemplate的EntityManagerFactory创建它。
final EntityManager em = jpaTemplate.getEntityManagerFactory().createEntityManager();
return new QueryIterator<T>(em.createQuery("FROM Foo"));
显然不是。似乎必须以不同的方式获得EntityManager。如下文所述。
jpaTemplate.execute(new JpaCallback() {
@Override
public Object doInJpa(final EntityManager em) throws PersistenceException {
return new QueryIterator<T>(em.createQuery("FROM Foo"));
}
});
现在一切正常。正如它应该是,无论交易是否存在。 : - )