Java 在另一个spring上下文中启动的功能测试中的回滚事务
我正在实施功能测试。为了避免数据损坏,我需要在执行后回滚每个测试。这是一项非常简单的任务——只需在测试中标记rollback=true。但如果我用另一个spring上下文启动另一个模块,第一个模块以某种方式与之交互,f.e.发送jms消息,第二个模块将其保存到同一个DB,那么回滚在第二个上下文中不起作用。如何也回滚第二个模块Java 在另一个spring上下文中启动的功能测试中的回滚事务,java,spring,hibernate,transactions,rollback,Java,Spring,Hibernate,Transactions,Rollback,我正在实施功能测试。为了避免数据损坏,我需要在执行后回滚每个测试。这是一项非常简单的任务——只需在测试中标记rollback=true。但如果我用另一个spring上下文启动另一个模块,第一个模块以某种方式与之交互,f.e.发送jms消息,第二个模块将其保存到同一个DB,那么回滚在第二个上下文中不起作用。如何也回滚第二个模块 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:/my-servi
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:/my-service-context.xml")
@Transactional(value = "myTransactionManager")
public class ParserServiceTest {
protected Logger l = LoggerFactory.getLogger(getClass());
@Autowired
@Qualifier(value = "earMessageDaoBean")
EARMessageDao dao;
@Autowired
@Qualifier(value = "myParserService")
ParserService service;
@Test
@Rollback(value = true)
public void testExecute() throws Exception {
service.execute("fff", "ttt");
EARMessage byId = dao.findById(1L);
assertNotNull(byId);
assertEquals("fff", byId.getFrom());
assertEquals("ttt", byId.getTo());
l.info("{}", byId);
}
}
如果我查看数据库,我将看不到任何数据,这是很好的
但是如果我要添加另一个模块
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:/my-service-context.xml")
@Transactional(value = "myTransactionManager")
public class ParserServiceTest {
protected Logger l = LoggerFactory.getLogger(getClass());
ClassPathXmlApplicationContext context2;
@Before
public void setUp() throws Exception {
context2 = new ClassPathXmlApplicationContext(
"my-service-context2.xml"
);
}
@Autowired
@Qualifier(value = "earMessageDaoBean")
EARMessageDao dao;
@Autowired
@Qualifier(value = "myParserService")
ParserService service;
@Test
@Rollback(value = true)
public void testExecute() throws Exception {
service.execute("fff", "ttt");
EARMessage byId = dao.findById(1L);
assertNotNull(byId);
assertEquals("fff", byId.getFrom());
assertEquals("ttt", byId.getTo());
l.info("{}", byId);
// theoretically there could be interaction with service2 via JMS
MyParserService2 service2 = (MyParserService2) context2.getBean("myParserService2");
service2.execute("FFF", "TTT");
}
}
服务2添加的数据将不会回滚
我可以在测试上下文中获取EntityManager TransactionManager,但我无法回滚它们,因为事务已经提交。
我可以在第二个模块中添加一些标记,并在测试中标记它,但现在还不知道该怎么做
更新
以下是用于更好理解的服务和上下文配置:
@Service(value = "myParserService")
@Transactional(value = "myTransactionManager")
public class ParserService {
protected Logger l = LoggerFactory.getLogger(getClass());
@Autowired
@Qualifier(value = "earMessageDaoBean")
EARMessageDao dao;
public void execute(String from, String to) {
l.info("-------started service 1---------");
EARMessage message = new EARMessage();
message.setFrom(from);
message.setTo(to);
message.setProcessingDate(new DateTime());
dao.persist(message);
l.info("-------ended service 1---------");
}
}
@Service(value = "myParserService2")
@Transactional(value = "myTransactionManager")
public class MyParserService2 {
protected Logger l = LoggerFactory.getLogger(getClass());
@Autowired
@Qualifier(value = "earMessageDaoBean")
EARMessageDao dao;
public void execute(String from, String to) {
l.info("-------started service 2---------");
EARMessage message = new EARMessage();
message.setFrom("666" + from);
message.setTo("666" + to);
message.setProcessingDate(new DateTime());
dao.persist(message);
l.info("-------ended service 2---------");
}
}
my-service-context.xml
<context:annotation-config/>
<context:component-scan base-package="com.dimas.tutorial.hibernate.simple"/>
<import resource="classpath:/my-service-config.xml"/>
<import resource="classpath:/my-data-source.xml"/>
<import resource="classpath:/my-entity-manager.xml"/>
<jdbc:initialize-database data-source="${dataSource.name}">
<jdbc:script location="classpath:/sql/my-schema.sql"/>
</jdbc:initialize-database>
my-service-context2.xml
<context:annotation-config/>
<context:component-scan base-package="com.dimas.tutorial.hibernate.simple"/>
<import resource="classpath:/my-service-config.xml"/>
<import resource="classpath:/my-data-source.xml"/>
<import resource="classpath:/my-entity-manager.xml"/>
<jdbc:initialize-database data-source="${dataSource.name}">
<jdbc:script location="classpath:/sql/my-schema.sql"/>
</jdbc:initialize-database>
UPDATE2:添加了实体管理器配置
<bean id="valettaEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="MyPersistence"/>
<property name="packagesToScan" value="com.dimas.tutorial.hibernate.simple.domain"/>
<property name="dataSource" ref="${dataSource.name}"/>
<property name="jpaVendorAdapter" ref="hibernateVendor"/>
<property name="jpaPropertyMap" ref="jpaPropertyMap"/>
</bean>
<util:map id="jpaPropertyMap">
<entry key="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
<entry key="hibernate.default_schema" value="public"/>
<entry key="hibernate.show_sql" value="false"/>
<entry key="hibernate.format_sql" value="false"/>
<entry key="hibernate.cache.use_second_level_cache" value="false"/>
<entry key="hibernate.max_fetch_depth" value="3"/>
<entry key="hibernate.jdbc.fetch_size" value="50"/>
<entry key="hibernate.jdbc.batch_size" value="10"/>
</util:map>
<bean id="hibernateVendor" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="false"/>
</bean>
<bean id="myTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="valettaEntityManagerFactory"/>
</bean>
<bean id="valettaTransactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="myTransactionManager"/>
</bean>
<context:annotation-config/>
<tx:annotation-driven transaction-manager="myTransactionManager"/>
使用您的服务所需的传播。 如。 第一笔交易:
@Transactional(value = "myTransactionManager")
public class ParserServiceTest {
通过请求事务加入:
通过请求事务加入:
所需的信息:
Spring REQUIRED行为意味着,如果当前bean方法执行上下文中存在已打开的事务,则将使用相同的事务。如果不存在,则创建一个新的。
简而言之,这意味着如果inner2nd事务方法导致事务回滚,则最外层的事务方法将无法提交,并且也将回滚事务。hmm,不,不工作,仍然有来自第二个服务的更新HMM获得异常org.springframework.transaction.NestedTransactionNotSupportedException:JpaDialect不支持保存点-检查您的JPA提供商的能力我很抱歉。如果它不是用方言实现的,它就不可用,也可能意味着它在hibernate中不受支持。恐怕用spring无法解决这个问题。可能我需要使用jdbc层的保存点
@Transactional(value = "myTransactionManager", propagation=Propagation.REQUIRED)
public class ParserService {
@Transactional(value = "myTransactionManager", propagation=Propagation.REQUIRED)
public class MyParserService2 {