使用Spring的SpringDessionContext测试Hibernate与Spring的EmbeddedDatabaseBuilder问题

时间:2015-06-04 10:45:17

标签: spring hibernate unit-testing junit4 spring-jdbc

我使用Spring Framework' EmbeddedDatabaseBuilder作为数据源进行单元测试,并使用Spring 4和Hibernate 4将其传递到我的SessionFactory的Hibernate配置中。我是不以任何方式使用Spring上下文 - 我使用的唯一配置是编程的(没有注释,除了Hibernate映射文件之外没有XML)。

我预计Hibernate将使用其默认的ThreadLocalSessionContext,并且我将能够在单元测试中启动和回滚事务。

但是Hibernate已经将其SessionFactory.currentSessionContext设置为Spring SpringSessionContext,每当我尝试拨打SessionFactory.getCurrentSession()时就会抱怨:

HibernateException: Could not obtain transaction-synchronized Session for current thread
    at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:134)
    at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:1014)

在我的单元测试中的以下代码中,我已将hibernate.current_session_context_class设置为 thread ,但这会被忽略或替换为Spring实现。

public abstract class HibernateTestBase {

    private static EmbeddedDatabase dataSource;
    private static SessionFactory sessionFactory;
    private Session session;

    @BeforeClass
    public static void setupClass() {
        dataSource = new EmbeddedDatabaseBuilder().
                setType(EmbeddedDatabaseType.H2).
                addScript("file:SQLResources/schema-1.1.sql").
                addScript("file:SQLResources/schema-1.2.sql").
                build();
        Configuration configuration = new Configuration();
        configuration.addResource("hibernate-mappings/HierarchyLevel.hbm.xml");
        configuration.addResource("hibernate-mappings/HierarchyFilter.hbm.xml");
        configuration.addResource("hibernate-mappings/AuditLog.hbm.xml");
        configuration.setProperty("hibernate.dialect",
                "org.hibernate.dialect.Oracle10gDialect");
        configuration.setProperty("hibernate.show_sql", "true");
        configuration.setProperty("hibernate.current_session_context_class",
                "thread");
        StandardServiceRegistryBuilder serviceRegistryBuilder =
                new StandardServiceRegistryBuilder();
        serviceRegistryBuilder.applySetting(Environment.DATASOURCE, dataSource);
        serviceRegistryBuilder.applySettings(configuration.getProperties());
        StandardServiceRegistry serviceRegistry =
                serviceRegistryBuilder.build();
        sessionFactory = configuration.buildSessionFactory(serviceRegistry);
        sessionFactory.openSession();
    }

    @AfterClass
    public static void tearDown() {
        if (sessionFactory != null) {
            sessionFactory.close();
        }
        if (dataSource != null) {
            dataSource.shutdown();
        }
    }

    @Before
    public final void startTransaction() {
        session = sessionFactory.getCurrentSession();
        session.beginTransaction();
    }

    @After
    public final void rollBack() {
        session.flush();
        Transaction transaction = session.getTransaction();
        transaction.rollback();
    }
}

我被迫拨打SessionFactory.openSession(),但之后我无法使用相同SessionFactory的DAO,因为他们都拨打getCurrentSession()。因此,我无法从已编码的数据处理功能中受益。

我该怎么办?

1 个答案:

答案 0 :(得分:0)

使用传统match "favorites_controller/:book_id" => "favorites#create", :as => :favourite 使用Configuration设置hibernate.cfg.xml对象时,它可以正常工作,如下所示:

SpringSessionContext

并在测试中加载它,但是像这样覆盖<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "classpath://org/hibernate/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</property> <property name="hibernate.show_sql">true</property> <property name="hibernate.current_session_context_class">org.springframework.orm.hibernate4.SpringSessionContext</property> <!-- property name="hibernate.current_session_context_class">thread</property--> <mapping resource="hibernate-mappings/AccessRight.hbm.xml" /> </session-factory> </hibernate-configuration>

session context

因此,当Hibernate使用所需的 Configuration configuration = new Configuration(); configuration.configure( "hibernate-mappings/hibernate.cfg.xml"); configuration.setProperty("hibernate.current_session_context_class", "thread"); 设置自己时,后台会发生一些事情。