Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/322.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在另一个spring上下文中启动的功能测试中的回滚事务_Java_Spring_Hibernate_Transactions_Rollback - Fatal编程技术网

Java 在另一个spring上下文中启动的功能测试中的回滚事务

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

我正在实施功能测试。为了避免数据损坏,我需要在执行后回滚每个测试。这是一项非常简单的任务——只需在测试中标记rollback=true。但如果我用另一个spring上下文启动另一个模块,第一个模块以某种方式与之交互,f.e.发送jms消息,第二个模块将其保存到同一个DB,那么回滚在第二个上下文中不起作用。如何也回滚第二个模块

    @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 {