0

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の実際のバージョンをDBに要求します。次に、いくつかの機能が実行され、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>

追加したいのですが、その時点で作成されたスレッドは1つだけで、データベース内のTestCaseデータにアクセスするスレッドは他にありません。唯一の問題は、getTestCaseが古いバージョンのTestCaseレコードを返すことですが、その理由はわかりません。

アドバイスありがとうございます。

4

1 に答える 1

0

問題は、休止状態のセッションが現在のスレッドにバインドされていることです。したがって、1 つの解決策は、スレッドを使用しないか、スレッドのセッションを処理するトランザクション インターセプターを作成することです。Springの詳細を参照ProxyFactoryBean からプロトタイプ スコープで Bean を取得する方法

于 2012-12-03T19:41:30.470 に答える