在 Spring+Hibernate 测试用例中重新加载数据库连接
我有一套使用 Spring 的 JUnit 运行程序的系统测试,数据库配置如下所示:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="org.postgresql.Driver" />
<property name="url" value="${clustercatalog.jdbc.url}" />
<property name="username" value="${clustercatalog.jdbc.username}" />
<property name="password" value="${clustercatalog.jdbc.password}" />
<property name="initialSize" value="5" />
<property name="maxActive" value="50" />
<property name="poolPreparedStatements" value="true" />
<property name="maxOpenPreparedStatements" value="100" />
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.xxx" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
<prop key="hibernate.show_sql">${jdbc.show.sql}</prop>
<prop key="hibernate.id.new_generator_mappings">true</prop>
</props>
</property>
<property name="namingStrategy" ref="namingStrategy" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven />
测试用例有一个设置,其中我运行一些 bash 脚本,这些脚本从以前完成的备份中在底层 PostgreSQL 数据库上运行 pg_restore。这是因为我需要在每个测试方法之前数据库的相同状态都相同。此恢复是在用 @BeforeTransaction 注释的方法中完成的。
测试类注释为
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({ "/systemTests-applicationContext.xml", "/applicationContext.xml" })
@TransactionConfiguration(defaultRollback = false)
@Transactional()
在测试中,当我执行使用当前休眠会话的代码时,它看不到已恢复的表。当我重新启动整个测试时,就会看到它们,但显然这就是我想要的,但它证明数据库很好,但当我执行 pg_restore 时,Spring/Hibernate 丢失了。我收到 SQLGrammarException 该表不存在。
我正在寻找一种手动重新启动与数据库的连接的方法。我怎样才能做到这一点?我应该在 sessionFactory 或某些 Spring 组件上以某种方式执行此操作吗?
I have a suite of system tests that uses Spring's JUnit runner, the database config looks like this:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="org.postgresql.Driver" />
<property name="url" value="${clustercatalog.jdbc.url}" />
<property name="username" value="${clustercatalog.jdbc.username}" />
<property name="password" value="${clustercatalog.jdbc.password}" />
<property name="initialSize" value="5" />
<property name="maxActive" value="50" />
<property name="poolPreparedStatements" value="true" />
<property name="maxOpenPreparedStatements" value="100" />
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.xxx" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
<prop key="hibernate.show_sql">${jdbc.show.sql}</prop>
<prop key="hibernate.id.new_generator_mappings">true</prop>
</props>
</property>
<property name="namingStrategy" ref="namingStrategy" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven />
The test case has a setup in which I run some bash scripts that run pg_restore on the underlying PostgreSQL database from a previously done backup. This is because I need the same state of the database to be the same before every test method. This restore is done in a method annontated with @BeforeTransaction.
The test class is annotated with
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({ "/systemTests-applicationContext.xml", "/applicationContext.xml" })
@TransactionConfiguration(defaultRollback = false)
@Transactional()
In the test when I execute code that uses the current hibernate session, it doesn't see the tables that were restored. When I restart the whole test then is sees them, but obviously this is what I want but it proves that the db is fine but Spring/Hibernate got lost when I did pg_restore. I get SQLGrammarException's that the table does not exist.
I'm looking for a way to manually restart the connection to the DB. How can I achieve that? Should I do it somehow on the sessionFactory or some Spring components?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
好的,我解决了这个问题。看来 Spring 和 Hibernate 都不知道数据库中发生的更改,并且如果 DBCP 池中有任何连接,它们会被重用,然后就会发生错误,因为连接下的架构已更改。所以我想,当我重置数据库时,在测试期间戳的地方是提供给 Hibernate SessionFactory 的 javax.sql.DataSource 对象。 DBCP BasicDataSource 不具备此功能,因此我:
代码如下:
applicationContext.xml:
OK, I resolved the issue. It appears that both Spring and Hibernate are unaware of the changes happening down in the DB and if there are any connections in the DBCP pool they are reused and then the error occurs, because the schema has changed underneath the connection. So I figured that the place to poke during the test when I reset the DBs is the javax.sql.DataSource object provided to the Hibernate SessionFactory. The DBCP BasicDataSource does not have this capability, thus I:
code follows:
applicationContext.xml: