我们有 java web 应用程序,我们正在使用 spring、hibernate3,我无法从 DB 获取实际版本的记录。
这是代码片段:
Class Scheduler
{
public void scheduleTests(………….)
{
.
.
.
TestCase testCase;
.
//Updating entity
getHibernateTemplate ().saveOrUpdate(testCase);
getHibernateTemplate ().flush();
.
.
.
Starts new thread
.
}
Thread run{
.
.
TestCase testCase = getTestCase(testCaseId);
.
.
.
.
updateTestCase(testCase);
}
getTestCase(testCaseId)
{
TestCase testCase = null;
try
{
testCase=(TestCase)getHibernateTemplate().get(TestCase.class, testCaseId);
}
catch (Exception ex)
{
ex.printStackTrace();
}
return testCase;
}
updateTestCase(TestCase testCase)
{
try
{
getHibernateTemplate ().saveOrUpdate(testCase);
getHibernateTemplate ().flush();
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
在方法计划测试中,我更改了对象 TestCase 并将其保存到数据库中。然后新线程开始,在这个线程的开头,我向 DB 询问 DB 的实际版本的 TestCase。然后执行一些功能,并将 TestCase 的最终状态更新为 DB。
问题是当我运行这个场景超过 1 次时。然后奇怪的事情发生了。在线程方法运行中,我从方法 getTestCase 旧版本的 TestCase 得到,然后更新崩溃,但出现以下异常:
错误
org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:300) - Could not synchronize database state with session
"org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [at.h3g.portal.db.webshop.WsRcCheck#405]
at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:1680)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2271)
at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2180)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2456)
at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:91)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:248)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:232)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:140)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:297)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:988)
at org.springframework.orm.hibernate3.HibernateTemplate$29.doInHibernate(HibernateTemplate.java:815)
at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:366)
at org.springframework.
ERROR org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:300) - Could not synchronize database state with session
"org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [at.h3g.portal.db.webshop.WsRcCheck#405]
at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:1680)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2271)
at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2180)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2456)
at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:91)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:248)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:232)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:140)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:297)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:988)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:337)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:584)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:500)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:473)
at org.springframework.transaction.interceptor.TransactionAspectSupport.doCommitTransactionAfterReturning(TransactionAspectSupport.java:267)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:170)
为什么我得到旧版本的 TestCase?我能做什么?这是Hibernate和Spring的配置。
在 Web.Xml 中:
<filter>
<filter-name>hibernateFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
<init-param>
<param-name>sessionFactoryBeanName</param-name>
<param-value>sessionFactory</param-value>
</init-param>
</filter>
和上下文配置:
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="mappingResources">
<list>
.
.
.
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.Oracle9Dialect
</prop>
<prop key="hibernate.connection.release_mode">
auto
</prop>
</props>
</property>
</bean>
<bean id="dataSource"
class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>java:comp/env/jdbc/SOMEDATASOURCE</value>
</property>
</bean>
<bean id="hibernateTemplate"
class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="sessionFactory" />
</property>
</bean>
<bean id="transactionInterceptorTestScheduling"
class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager">
<ref bean="transactionManager" />
</property>
<property name="transactionAttributeSource">
<value> org.company.db.Scheduler.updateTestCase=PROPAGATION_REQUIRES_NEW
</value>
</property>
</bean>
而且我想补充一下,当时只创建了一个线程,没有其他任何东西可以访问数据库中的TestCase数据。唯一的问题是 getTestCase 返回旧版本的 TestCase 记录,我现在不知道为什么。
谢谢你的建议。