java - Spring/JTA/JPA 单元测试 : Rollback not working

标签 java hibernate spring junit jta

我正在尝试使用 Spring 测试实体 EJB3。

EJB 本身不使用 Spring,我希望尽量减少生产 JPA 配置的重复(例如,不复制 persistence.xml)。

我的单元测试似乎可以工作,但即使我的单元测试应该是事务性的,数据也会在各种测试方法之间保留...

这是我的实体:

package sample;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class Ejb3Entity {

    public Ejb3Entity(String data) {
        super();
        this.data = data;
    }
    private Long id;
    private String data;

    @Id
    @GeneratedValue
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }

    public String getData() {
        return data;
    }
    public void setData(String data) {
        this.data = data;
    }

}

我的单元测试:

package sample;

import static org.junit.Assert.*;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"/appContext.xml"})
@Transactional
public class Ejb3EntityTest {

    @PersistenceContext
    EntityManager em;

    @Before
    public void setUp() throws Exception {
        Ejb3Entity one = new Ejb3Entity("Test data");
        em.persist(one);
    }

    @Test
    public void test1() throws Exception {

        Long count = (Long) em.createQuery("select count(*) from Ejb3Entity").getSingleResult();
        assertEquals(Long.valueOf(1l), count);
    }

    @Test
    public void test2() throws Exception {

        Long count = (Long) em.createQuery("select count(*) from Ejb3Entity").getSingleResult();
        assertEquals(Long.valueOf(1l), count);
    }

}

和我的 appContext.xml :

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/tx
           http://www.springframework.org/schema/tx/spring-tx.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context.xsd">

    <bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBean" />

    <bean id="transactionManager"
        class="org.springframework.transaction.jta.JtaTransactionManager">
        <property name="userTransaction" ref="jotm" />
        <property name="allowCustomIsolationLevels" value="true" />
    </bean>

    <bean id="dataSource" class="org.enhydra.jdbc.standard.StandardXADataSource">
        <property name="driverName" value="org.h2.Driver" />
        <property name="url" value="jdbc:h2:mem:unittest;DB_CLOSE_DELAY=-1" />
        <property name="user" value="" />
        <property name="password" value="" />
        <property name="transactionManager" ref="jotm" />
    </bean>

    <bean id="emf"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceUnitPostProcessors">
            <bean class="sample.JtaDataSourcePersistenceUnitPostProcessor">
                <property name="jtaDataSource" ref="dataSource" />
            </bean>
        </property>
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="showSql" value="false" />
                <property name="generateDdl" value="true" />
                <property name="database" value="H2" />
                <property name="databasePlatform" value="org.hibernate.dialect.H2Dialect" />
            </bean>
        </property>
        <property name="jpaPropertyMap">
            <map>
                <entry key="hibernate.transaction.manager_lookup_class"
                    value="org.hibernate.transaction.JOTMTransactionManagerLookup" />
                <entry key="hibernate.transaction.auto_close_session" value="false" />
                <entry key="hibernate.current_session_context_class" value="jta" />
            </map>
        </property>

    </bean>


</beans>

当我运行我的测试时,test2 失败了,因为它发现了 2 个实体,而我只希望有一个实体(因为第一个实体应该被回滚......)

我尝试了很多不同的配置,这个似乎是我能得到的最全面的……我没有其他想法。你呢?

最佳答案

当我尝试集成 JOTM 和 Hibernate 时,我最终不得不编写 ConnectionProvider 的实现代码。这是它现在的样子:http://pastebin.com/f78c66e9c

然后您将您的实现指定为 hibernate 属性中的连接提供者,事务神奇地开始工作。

问题是默认连接提供程序在数据源上调用 getConnection()。在您自己的实现中,您调用 getXAConnection().getConnection()。这就是区别

关于java - Spring/JTA/JPA 单元测试 : Rollback not working,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1519968/

相关文章:

java - 游戏的重复方法

java - 似乎 Set-Cookie 的过期格式为 Mon, 25 Sep 2017 13 :40:02 GMT could not be parsed my apache http client

spring - 在 Spring MVC 端点中使用多个 Pageable 参数

spring - 如何在两个应用程序之间共享同一个 session

java - 使用 Regex 和 Java 从文本中提取内容

java - 无法使用 Hibernate 从表中添加和删除数据

java - 我的 hibernate 事务和 session 出了什么问题

mysql - 插入日期字段mysql、struts2 spring hibernate

java - Spring 动态表单的更好方法?

java - 如何在运行 gradlecompileJava 时修复相关子项目中的 "Cannot find symbol error"