使用 Spring 的 EmbeddedDatabaseBuilder 测试 Hibernate 与 SpringSessionContext 的问题
testing Hibernate with Spring's EmbeddedDatabaseBuilder issues with SpringSessionContext
我正在使用 Spring 框架的 EmbeddedDatabaseBuilder
作为数据源进行单元测试,并将其传递到我的 SessionFactory
的 Hibernate 配置中,使用 Spring 4 和 Hibernate 4 . 我没有以任何方式使用 Spring 上下文 - 我使用的唯一配置是程序化的(没有注释,没有 XML 除了 Hibernate 映射文件)。
我希望 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()
,但之后我将无法将我的 DAO 与相同的 SessionFactory
一起使用,因为它们都调用 getCurrentSession()
。所以我将无法从已经编码的数据处理功能中受益。
我能做什么?
使用传统的 hibernate.cfg.xml
设置 Configuration
对象时工作正常,使用 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
:
Configuration configuration = new Configuration();
configuration.configure(
"hibernate-mappings/hibernate.cfg.xml");
configuration.setProperty("hibernate.current_session_context_class",
"thread");
因此,当 Hibernate 使用所需的 hibernate.cfg.xml
进行自我设置时,后台会发生一些事情。
我正在使用 Spring 框架的 EmbeddedDatabaseBuilder
作为数据源进行单元测试,并将其传递到我的 SessionFactory
的 Hibernate 配置中,使用 Spring 4 和 Hibernate 4 . 我没有以任何方式使用 Spring 上下文 - 我使用的唯一配置是程序化的(没有注释,没有 XML 除了 Hibernate 映射文件)。
我希望 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()
,但之后我将无法将我的 DAO 与相同的 SessionFactory
一起使用,因为它们都调用 getCurrentSession()
。所以我将无法从已经编码的数据处理功能中受益。
我能做什么?
使用传统的 hibernate.cfg.xml
设置 Configuration
对象时工作正常,使用 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
:
Configuration configuration = new Configuration();
configuration.configure(
"hibernate-mappings/hibernate.cfg.xml");
configuration.setProperty("hibernate.current_session_context_class",
"thread");
因此,当 Hibernate 使用所需的 hibernate.cfg.xml
进行自我设置时,后台会发生一些事情。