我写了一个扩展AbstractTransactionalJUnit4SpringContextTests
的测试用例。我编写的单个测试用例创建了一个类User实例,并尝试使用Hibernate将其写入数据库。然后,测试代码使用SimpleJdbcTemplate
从用户表执行简单的选择计数(*),以确定用户是否持久保存到数据库。但测试总是失败。我很怀疑,因为在我写的Spring控制器中,将用户实例保存到数据库的能力是成功的。
所以我将Rollback注释添加到单元测试中,果然,数据被写入数据库,因为我甚至可以在相应的表中看到它 - 当测试用例完成时,事务不会回滚。
这是我的测试用例:
@ContextConfiguration(locations = {
"classpath:context-daos.xml",
"classpath:context-dataSource.xml",
"classpath:context-hibernate.xml"})
public class UserDaoTest extends AbstractTransactionalJUnit4SpringContextTests {
@Autowired
private UserDao userDao;
@Test
@Rollback(false)
public void teseCreateUser() {
try {
UserModel user = randomUser();
String username = user.getUserName();
long id = userDao.create(user);
String query = "select count(*) from public.usr where usr_name = '%s'";
long count = simpleJdbcTemplate.queryForLong(String.format(query, username));
Assert.assertEquals("User with username should be in the db", 1, count);
}
catch (Exception e) {
e.printStackTrace();
Assert.assertNull("testCreateUser: " + e.getMessage());
}
}
}
我认为我没有添加配置文件。
上下文hibernate.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"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd>
<bean id="namingStrategy" class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean">
<property name="staticField">
<value>org.hibernate.cfg.ImprovedNamingStrategy.INSTANCE</value>
</property>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean" destroy-method="destroy" scope="singleton">
<property name="namingStrategy">
<ref bean="namingStrategy"/>
</property>
<property name="dataSource" ref="dataSource"/>
<property name="mappingResources">
<list>
<value>com/company/model/usr.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.use_sql_comments">true</prop>
<prop key="hibernate.query.substitutions">yes 'Y', no 'N'</prop>
<prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
<prop key="hibernate.cache.use_minimal_puts">false</prop>
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.current_session_context_class">thread</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
<property name="nestedTransactionAllowed" value="false" />
</bean>
<bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager">
<ref local="transactionManager"/>
</property>
<property name="transactionAttributes">
<props>
<prop key="create">PROPAGATION_REQUIRED</prop>
<prop key="delete">PROPAGATION_REQUIRED</prop>
<prop key="update">PROPAGATION_REQUIRED</prop>
<prop key="*">PROPAGATION_SUPPORTS,readOnly</prop>
</props>
</property>
</bean>
</beans>
上下文dataSource.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"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="org.postgresql.Driver" />
<property name="jdbcUrl" value="jdbc\:postgresql\://localhost:5432/company_dev" />
<property name="user" value="postgres" />
<property name="password" value="postgres" />
</bean>
</beans>
上下文daos.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"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="extendedFinderNamingStrategy" class="com.company.dao.finder.impl.ExtendedFinderNamingStrategy"/>
<bean id="finderIntroductionAdvisor" class="com.company.dao.finder.impl.FinderIntroductionAdvisor"/>
<bean id="abstractDaoTarget" class="com.company.dao.impl.GenericDaoHibernateImpl" abstract="true" depends-on="sessionFactory">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
<property name="namingStrategy">
<ref bean="extendedFinderNamingStrategy"/>
</property>
</bean>
<bean id="abstractDao" class="org.springframework.aop.framework.ProxyFactoryBean" abstract="true">
<property name="interceptorNames">
<list>
<value>transactionInterceptor</value>
<value>finderIntroductionAdvisor</value>
</list>
</property>
</bean>
<bean id="userDao" parent="abstractDao">
<property name="proxyInterfaces">
<value>com.company.dao.UserDao</value>
</property>
<property name="target">
<bean parent="abstractDaoTarget">
<constructor-arg>
<value>com.company.model.UserModel</value>
</constructor-arg>
</bean>
</property>
</bean>
</beans>
其中一些我从别人那里继承了。我不会使用正在进行的代理,因为我不确定它是否需要,但这正是我正在使用的。
任何帮助都非常感激。
答案 0 :(得分:1)
IIRC,Hibernate(和其他O / R映射器)延迟数据库INSERT和UPDATE语句,直到事务提交。然后SELECT没有看到数据,因为它尚未写入。尝试明确请求会话刷新。
另见文档以获得解释和示例: http://docs.jboss.org/hibernate/core/3.3/reference/en/html/objectstate.html#objectstate-flushing
答案 1 :(得分:0)
transactionInterceptor不会自动提交吗?
第117行:
commitTransactionAfterReturning(txInfo);
默认情况下,刷新模式应该是auto,因此执行commit时应该有一个隐式刷新。我有同样的问题,不得不通过手动调用flush来解决它。这是非常不满意的,因为我的现有代码在迁移到Spring transation manager之前依赖于自动刷新。我希望有一种方法可以告诉org.springframework.orm.hibernate3.HibernateTransactionManager在提交后进行刷新。