Тупик в приложении Spring+Hibernate+DB2+JTA+XA

Исключение из журнала приложений:

12:04:18,503  INFO ExceptionResolver:30 -  [ org.springframework.dao.DeadlockLoserDataAccessException ] Hibernate flushing: could not update: [sero.chase.integration.Beans.Bean#1000]; SQL [update SCHM.v***240u_bean set prop1=?, prop2=?, prop3=?, prop4=?, prop5=?, prop6=?, prop7=?, prop8=?, prop9=?, prop10=?, prop11=?, prop12=?, prop13=?, prop14=?, prop15=?, prop16=?, prop17=?, prop18=?, prop19=?, prop20=?, prop21=?, where bean_id=?]; UNSUCCESSFUL EXECUTION CAUSED BY DEADLOCK OR TIMEOUT. REASON CODE 00C90088, TYPE OF RESOURCE 00000302, AND RESOURCE NAME SCHM.SAKT240 .X'000017'. SQLCODE=-913, SQLSTATE=57033, DRIVER=3.53.70; nested exception is com.ibm.db2.jcc.b.SqlException: UNSUCCESSFUL EXECUTION CAUSED BY DEADLOCK OR TIMEOUT. REASON CODE 00C90088, TYPE OF RESOURCE 00000302, AND RESOURCE NAME SCHM.SAKT240 .X'000017'. SQLCODE=-913, SQLSTATE=57033, DRIVER=3.53.70org.springframework.dao.DeadlockLoserDataAccessException: Hibernate flushing: could not update: [sero.chase.integration.Beans.Bean#1000]; SQL [update SCHM.v***240u_bean set prop1=?, prop2=?, prop3=?, prop4=?, prop5=?, prop6=?, prop7=?, prop8=?, prop9=?, prop10=?, prop11=?, prop12=?, prop13=?, prop14=?, prop15=?, prop16=?, prop17=?, prop18=?, prop19=?, prop20=?, prop21=?, where bean_id=?]; UNSUCCESSFUL EXECUTION CAUSED BY DEADLOCK OR TIMEOUT. REASON CODE 00C90088, TYPE OF RESOURCE 00000302, AND RESOURCE NAME SCHM.SAKT240 .X'000017'. SQLCODE=-913, SQLSTATE=57033, DRIVER=3.53.70; nested exception is com.ibm.db2.jcc.b.SqlException: UNSUCCESSFUL EXECUTION CAUSED BY DEADLOCK OR TIMEOUT. REASON CODE 00C90088, TYPE OF RESOURCE 00000302, AND RESOURCE NAME MWIAKT1 .SAKT240 .X'000017'. SQLCODE=-913, SQLSTATE=57033, DRIVER=3.53.70
    at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:265)
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)
    at org.springframework.orm.hibernate3.HibernateTransactionManager.convertJdbcAccessException(HibernateTransactionManager.java:805)
    at org.springframework.orm.hibernate3.HibernateTransactionManager.convertHibernateAccessException(HibernateTransactionManager.java:791)
    at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:664)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:393)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
    at $Proxy54.save(Unknown Source)
    at sero.chase.integration.DaoImpl.ExampleDaoImpl.save(ExampleDaoImpl.java:151)
    at sero.chase.business.BOImpl.ExampleBOImpl.save(ExampleBOImpl.java:191)
    at sero.chase.ServicesImpl.ExampleServiceImpl.submitAnswer(ExampleServiceImpl.java:183)
    at sero.chase.business.BusDelegatesImpl.ExampleBusDelegateImpl.gradeAnswer(ExampleBusDelegateImpl.java:578)
    at sero.chase.presentation.Controller.ExampleController.gradeAnswer(ExampleController.java:326)
    at sero.chase.presentation.Controller.ExampleController.SubmitAnswer(ExampleController.java:422)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:79)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:618)
    at org.springframework.web.servlet.mvc.multiaction.MultiActionController.invokeNamedMethod(MultiActionController.java:471)
    at org.springframework.web.servlet.mvc.multiaction.MultiActionController.handleRequestInternal(MultiActionController.java:408)
    at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153)
    at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:900)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:827)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:789)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:763)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:856)
    at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1152)
    at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1087)
    at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:118)
    at com.ibm.ws.webcontainer.filter.WebAppFilterChain._doFilter(WebAppFilterChain.java:87)
    at com.ibm.ws.webcontainer.filter.WebAppFilterManager.doFilter(WebAppFilterManager.java:840)
    at com.ibm.ws.webcontainer.filter.WebAppFilterManager.doFilter(WebAppFilterManager.java:683)
    at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:589)
    at com.ibm.ws.wswebcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:534)
    at com.ibm.ws.webcontainer.servlet.CacheServletWrapper.handleRequest(CacheServletWrapper.java:90)
    at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:751)
    at com.ibm.ws.wswebcontainer.WebContainer.handleRequest(WebContainer.java:1478)
    at com.ibm.ws.webcontainer.channel.WCChannelLink.ready(WCChannelLink.java:126)
    at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:458)
    at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleNewInformation(HttpInboundLink.java:387)
    at com.ibm.ws.http.channel.inbound.impl.HttpICLReadCallback.complete(HttpICLReadCallback.java:102)
    at com.ibm.ws.tcp.channel.impl.AioReadCompletionListener.futureCompleted(AioReadCompletionListener.java:165)
    at com.ibm.io.async.AbstractAsyncFuture.invokeCallback(AbstractAsyncFuture.java:217)
    at com.ibm.io.async.AsyncChannelFuture.fireCompletionActions(AsyncChannelFuture.java:161)
    at com.ibm.io.async.AsyncFuture.completed(AsyncFuture.java:136)
    at com.ibm.io.async.ResultHandler.complete(ResultHandler.java:196)
    at com.ibm.io.async.ResultHandler.runEventProcessingLoop(ResultHandler.java:751)
    at com.ibm.io.async.ResultHandler$2.run(ResultHandler.java:881)
    at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1497)
Caused by: com.ibm.db2.jcc.b.SqlException: UNSUCCESSFUL EXECUTION CAUSED BY DEADLOCK OR TIMEOUT. REASON CODE 00C90088, TYPE OF RESOURCE 00000302, AND RESOURCE NAME MWIAKT1 .SAKT240 .X'000017'. SQLCODE=-913, SQLSTATE=57033, DRIVER=3.53.70
    at com.ibm.db2.jcc.b.bd.a(bd.java:679)
    at com.ibm.db2.jcc.b.bd.a(bd.java:60)
    at com.ibm.db2.jcc.b.bd.a(bd.java:127)
    at com.ibm.db2.jcc.b.fm.b(fm.java:2132)
    at com.ibm.db2.jcc.b.fm.c(fm.java:2115)
    at com.ibm.db2.jcc.t4.db.k(db.java:353)
    at com.ibm.db2.jcc.t4.db.a(db.java:59)
    at com.ibm.db2.jcc.t4.t.a(t.java:50)
    at com.ibm.db2.jcc.t4.tb.b(tb.java:200)
    at com.ibm.db2.jcc.b.gm.Zb(gm.java:2445)
    at com.ibm.db2.jcc.b.gm.e(gm.java:3287)
    at com.ibm.db2.jcc.b.gm.Rb(gm.java:612)
    at com.ibm.db2.jcc.b.gm.executeUpdate(gm.java:595)
    at com.ibm.ws.rsadapter.jdbc.WSJdbcPreparedStatement.executeUpdate(WSJdbcPreparedStatement.java:768)
    at org.hibernate.jdbc.NonBatchingBatcher.addToBatch(NonBatchingBatcher.java:23)
    at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2399)
    at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2303)
    at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2603)
    at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:92)
    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:298)
    at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
    at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
    at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
    at org.hibernate.transaction.JTATransaction.commit(JTATransaction.java:135)
    at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:656)
    ... 50 more

Конфигурация пружины:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:jee="http://www.springframework.org/schema/jee" 
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans         
                           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd         
                           http://www.springframework.org/schema/context         
                           http://www.springframework.org/schema/context/spring-context-3.0.xsd
                           http://www.springframework.org/schema/jee
                           http://www.springframework.org/schema/jee/spring-jee-3.0.xsd">

    <jee:jndi-lookup id="queueConFac" resource-ref="true" jndi-name="jms/queueConFac" />
    <jee:jndi-lookup id="receiveQ" resource-ref="true" jndi-name="jms/receiveQ" />
    <jee:jndi-lookup id="sendQ" resource-ref="true" jndi-name="jms/sendQ" />
    <jee:jndi-lookup id="XA" resource-ref="true" jndi-name="jdbc/XA" />
    <jee:jndi-lookup id="nonXA" resource-ref="true" jndi-name="jdbc/nonXA" />


    <bean id="jmsTxManager"
    class="org.springframework.transaction.jta.WebSphereUowTransactionManager"/> 

    <bean id="jmsDestResolver" class=" org.springframework.jms.support.destination.JndiDestinationResolver"/>   

    <bean id="exampleListener" class="sero.chase.integration.JMS.Services.JMSReceiver">
        <property name="exampleAppBusDelegate" ref="exampleAppBusDelegate" />
    </bean>

    <bean class="org.springframework.jms.listener.DefaultMessageListenerContainer" >
        <property name="connectionFactory" ref="queueConFac" />
        <property name="destination" ref="receiveQ" />
        <property name="messageListener" ref="exampleListener" />
        <property name="transactionManager" ref="jmsTxManager" />
        <property name="taskExecutor" ref="jmsTaskExecutor" />
    </bean>

    <bean id="jmsTaskExecutor"
      class="org.springframework.scheduling.commonj.WorkManagerTaskExecutor">
      <property name="workManagerName" value="wm/default" />
   </bean>

   <bean id="jmsSender" class="sero.chase.integration.JMS.Services.JMSSender">
        <property name="connectionFactory" ref="queueConFac" />
        <property name="queue" ref="sendQ" />
    </bean>

    <bean id="localeResolver"
        class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
        <property name="defaultLocale" value="en" />
    </bean>

    <bean id="localeChangeInterceptor"
        class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
        <property name="paramName" value="language" />
    </bean>

    <bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping" >
        <property name="interceptors">
            <list>
                <ref bean="localeChangeInterceptor" />
            </list>
        </property>
    </bean>

    <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <property name="basename" value="WEB-INF/resources/langSpecificText"/>
    </bean> 

    <bean id="viewResolver"
        class="org.springframework.web.servlet.view.UrlBasedViewResolver">
        <property name="viewClass"
            value="org.springframework.web.servlet.view.tiles2.TilesView" />
    </bean>

    <bean id="tilesConfigurer"
        class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
        <property name="definitions">
            <list>
                <value>/WEB-INF/tiles-def.xml</value>
            </list>
        </property>
    </bean>

    <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiName" value="jdbc/nonXA" />
    </bean>

    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="dataSource"     ref="nonXA" />
        <property name="configLocation" value="classpath:/hibernate.cfg.nonXA.xml" />
        <property name="entityInterceptor">
            <bean class="sero.chase.integration.Hibernate.DB2Interceptor"/>
        </property>
    </bean>

    <bean id="session.XA.Factory"
        class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="dataSource"     ref="XA" />
        <property name="configLocation" value="classpath:/hibernate.cfg.XA.xml" />
        <property name="entityInterceptor">
            <bean class="sero.chase.integration.Hibernate.DB2Interceptor"/>
        </property>
    </bean>

    <bean id="transactionManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

    <bean id="transaction.XA.Manager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="session.XA.Factory" />
    </bean>

    <bean id="transactionAttributeSource"
        class="org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource">
        <property name="properties">
            <props>
                <prop key="*">PROPAGATION_REQUIRED</prop>
            </props>
        </property>
    </bean>

    <!-- App Bean Definitions (Two dao configurations excluding several other bean configurations are displayed below) -->

    <bean id="exampleDao"
        class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
        lazy-init="true">
        <property name="transactionManager"         ref="transactionManager" />
        <property name="transactionAttributeSource" ref="transactionAttributeSource" />
        <property name="target">
            <bean class="sero.chase.integration.PersistenceImpl.ExamplePersistenceImpl">
                <property name="sessionFactory"     ref="sessionFactory" />
            </bean>
        </property>
    </bean>

     <bean id="exampleXADao"
        class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
        lazy-init="true">
        <property name="transactionManager"         ref="transaction.XA.Manager" />
        <property name="transactionAttributeSource" ref="transactionAttributeSource" />
        <property name="target">
            <bean class="sero.chase.integration.PersistenceImpl.ExamplePersistenceImpl">
                <property name="sessionFactory"     ref="session.XA.Factory" />
            </bean>
        </property>
    </bean>

</beans>

Конфигурация Hibernate Non XA:

<hibernate-configuration>

        <session-factory>

             <property name="hibernate.dialect">
                sero.chase.integration.Hibernate.DB2390Dialect
            </property>

            <property name="hibernate.default_schema">SCHM</property>
            <property name="query.substitutions">yes 'Y', no 'N'</property>
            <property name="jdbc.use_streams_for_binary">true</property>
            <property name="show_sql">true</property>
            <property name="format_sql">true</property>
            <property name="transaction.factory_class">org.hibernate.transaction.JTATransactionFactory</property>
            <property name="jta.UserTransaction">java:comp/UserTransaction</property>

            <property name="hibernate.cache.provider_class">
                org.hibernate.cache.EhCacheProvider
            </property>

            <!--===============-->
            <!-- mapping files -->
            <!--===============-->

            <mapping resource="sero/chase/integration/hbm/Example.hbm.xml" />

        </session-factory>

    </hibernate-configuration>

Конфигурация Hibernate XA:

<hibernate-configuration>

        <session-factory>

            <property name="hibernate.dialect">
                sero.chase.integration.Hibernate.DB2390Dialect
            </property>

            <property name="hibernate.default_schema">SCHMA</property>
            <property name="query.substitutions">yes 'Y', no 'N'</property>
            <property name="jdbc.use_streams_for_binary">true</property>
            <property name="show_sql">true</property>
            <property name="format_sql">true</property>
            <property name="hibernate.transaction.factory_class">org.hibernate.transaction.CMTTransactionFactory </property>
            <property name="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.WebSphereExtendedJTATransactionLookup</property> 

            <property name="hibernate.cache.provider_class">
                org.hibernate.cache.EhCacheProvider
            </property>

            <!--===============-->
            <!-- mapping files -->
            <!--===============-->

            <mapping resource="sero/chase/integration/hbm/Example.hbm.xml" />

        </session-factory>

    </hibernate-configuration>

Фрагмент кода из моего класса реализации сервиса, где происходит большая часть бизнес-логики:

public void someDeadlockCausingServiceMethod() {
    //The read1() method below is going to executing a select hql statement on Table A once the call goes all the way down to the Dao layer.
    List<SomeBeanInBusinessLayer> beanList = exampleBO.read1();

    //Do some processing with the values obtained from the read1() method
    ...
    //

    //saveOrUpdate() method below is going to execute an update hql statement on Table A once the call goes all the way down to the Dao layer 
    //where the values from someBeanInBusinessLayer is going to be copied into someBeanInDaoLayer before saving.
    exampleBO.saveOrUpdate(someBeanInBusinessLayer)

    //The read2() method below is going to execute a select hql statement that contains two inner selects (on Table B, C and D) once the call goes all
    //the way down to the Dao layer.
    List<SomeBeanInBusinessLayer2> beanList2 = exampleBO.read2();

    //Do some processing with the values obtained from the read2() method inside a for loop
    for(SomeBeanInBusinessLayer2 s: beanList2) {

        //Read values from table E
        List<SomeBeanInBusinessLayer3> beanList3 = exampleBO.read3(s.getProp2());

        SomeBeanInBusinessLayer2 someBeanInBusinessLayer2 = new SomeBeanInBusinessLayer2();
        someBeanInBusinessLayer2.setProp1(s.getProp2());
        someBeanInBusinessLayer2.setProp1(someBeanInBusinessLayer3.getProp2());
        //... more processing...
        //Below method will execute an insert hql on Table F
        exampleBO.saveOrUpdate(someBeanInBusinessLayer2);

        SomeBeanInBusinessLayer3 someBeanInBusinessLayer3 = new SomeBeanInBusinessLayer3();
        someBeanInBusinessLayer3.setProp1(s.getProp5());
        //... more processing...
        //Below method will execute an insert hql on Table G
        exampleBO.saveOrUpdate(someBeanInBusinessLayer3);
    }
}

public void anotherDeadlockCausingServiceMethod() {
    //The read1() method below is going to executing a select hql statement on Table A once the call goes all the way down to the Dao layer.
    List<SomeBeanInBusinessLayer> beanList = exampleBO.read1();

    //The read2() method below is going to executing a select hql statement on Table F once the call goes all the way down to the Dao layer.
    List<SomeBeanInBusinessLayer2> beanList2 = exampleBO.read2();

    //The read1() method below is going to executing a select hql statement on Table G once the call goes all the way down to the Dao layer.
    List<SomeBeanInBusinessLayer3> beanList3 = exampleBO.read3();

    //Do some processing with the values obtained...

    //Do an update on Table A
    exampleBO.saveOrUpdate(someBeanInBusinessLayer1)

    //Do an update on Table F
    exampleBO.saveOrUpdate(someBeanInBusinessLayer2)
}

Фрагмент кода из моего Dao layer1:

public void load(BeanDTO beanDTO) {
    Object param1 = beanDTO.getBeanList().getProp1();
    Object param2 = beanDTO.getBeanList().getProp2();
    List<SomeBeanInDaoLayer> beanList = null;
    Object[] params = {param1, param2};
          UserTransaction ut = null;
    try {
      Context context = new InitialContext();
      ut = (UserTransaction) context.lookup(Constant.USR_TRANSACTION);
      ut.begin();   
            beanList = beanDao2.load(params);
            ut.commit();
    }
    catch(Exception e) {
                    try {
                         ut.rollback();
                    }
                    catch(Exception e1) {
                    if(logger.isDebugEnabled()) {
           logger.debug("DB Exception", e1);
        }
                    }
        int error = ExceptionResolver.resolve(e);
        if(logger.isDebugEnabled()) {
            logger.debug("DB Exception", e);
        }
        beanDTO.setErrorCode(error);
    }
    beanDTO.setBeanList(beanList);
}

public void save(BeanDTO beanDTO) {
    List<SomeBeanInDaoLayer> beanList = beanDTO.getBeanList();
    for(SomeBeanInDaoLayer bean: beanList) {
        try {
                      Context context = new InitialContext();
                ut = (UserTransaction) context.lookup(Constant.USR_TRANSACTION);
                ut.begin(); 
                      beanDao2.save(bean);
                      ut.commit();
        }
        catch(Exception e) {
                       try {
                         ut.rollback();
                       }
                       catch(Exception e1) {
                         if(logger.isDebugEnabled()) {
               logger.debug("DB Exception", e1);
             }
                       }
            int err = ExceptionResolver.resolve(e);
            if(logger.isInfoEnabled()) {
                logger.info("DB Exception", e);
            }
            beanDTO.setErrorCode(err);
        }
    }
}

Кодовый фрагмент из моего Dao Layer2:

public List<Bean> load(Object[] params) {
    String hql = "from Bean where beanProp1 = ? and beanProp2 = ?";
    return (List<Bean>) getHibernateTemplate().find(hql, params);
}

public void save(Bean bean) {
    getHibernateTemplate().saveOrUpdate(bean);
}
  1. Это приложение представляет собой систему тестирования, где пользователи могут проходить тестирование одновременно.
  2. Первоначально разграничение транзакций происходило не на моем уровне Dao, а, скажем, на моем классе реализации сервиса (фактически, полностью на уровне моего контроллера), где несколько операций чтения и обновления были связаны в одну транзакцию в пределах блока begin-commit. Поскольку я видел несколько взаимоблокировок, я переместил демаркацию на слой Dao, чтобы между моим блоком begin-commit была только одна инструкция hql, чтобы увидеть, предотвращает ли она взаимоблокировку, но не повезло.
  3. Попытался установить для свойств, таких как hibernate.connection.autocommit значение true, для hibernate.transaction.flush_before_completion значение true, а hibehibernate.transaction.auto_close_session - значение true, но не повезло.
  4. Никогда строка, прочитанная одним пользователем, не обновляется другим пользователем. Каждый пользователь читает и обновляет разные строки, даже если они обращаются к одним и тем же таблицам DB2. Только во время запуска процесса создания набора вопросов для теста два пользователя будут читать одни и те же строки, если они будут проходить один и тот же тип теста. Он очень похож на описанный выше метод someDeadlockCausingMetho, где тестовые вопросы готовятся из набора таблиц, содержащих вопросы и ответы. После итерации по этому результирующему набору внутри цикла for новые строки вставляются в другую таблицу, чтобы сохранить детали каждого вопроса, который появится в тесте пользователя. Этот шаг необходим в приложении, поскольку, хотя два пользователя сдают один и тот же тест, набор случайных вопросов берется из пула всех вопросов для каждого пользователя.
  5. Теперь, когда тест подготовлен для того, чтобы пользователь прошел тест, следующим логическим шагом в приложении является чтение строк из таблицы, которые содержат только детали вопросов, относящихся к пользователю, проходящему тест. Таким образом, параллельный пользователь будет читать одну и ту же таблицу во время этого процесса, но не одну и ту же строку Пользователю предоставляется один вопрос за раз. Как только пользователь отвечает на вопрос, строка, которая была прочитана, чтобы получить вопрос, относящийся только к этому пользователю, будет обновлена ​​с выбором ответа. Снова никогда не обновляются одинаковые строки для двух одновременно работающих пользователей. Этот метод аналогичен другому описанному выше DedelockCausingMethod().
  6. Я надеюсь, что вы поняли, что делает приложение. Тот факт, что параллельные пользователи никогда не читают и не обновляют одни и те же строки, удивил меня, как ресурс может быть заблокирован. Затем я понял, что для обновления таблиц была установлена ​​блокировка страниц. Поэтому я пошел и спросил администратора базы данных, может ли он изменить его на блокировку строк в обновляемых таблицах. Он обеспокоен повышением производительности в DB2 для реализации блокировки строк и обеспокоен, может ли это повлиять на другие приложения, использующие DB2. Поэтому он не хочет этого делать, если я не найду другого решения.
  7. Пожалуйста, забудьте часть XA/JMS. Предположим, что часть закомментирована на время. Для большей части приложения используется источник данных не-XA, где я вижу тупики.

    Может кто-нибудь сказать, пожалуйста, как мне решить проблему тупика? Я хочу понять, что пошло не так в дизайне. Любая помощь с благодарностью

2 ответа

Решение

Наконец, я справился без пробега, сделав следующее:

  1. hibernate.connection.isolation = 2
  2. Добавлено "для обновления с помощью cs" в конце моих операторов выбора.
  3. Я использовал метод спящего режима saveOrUpdate() для обновления и вставки. Теперь вместо этого я использую save() для вставки и update() для обновления.

Одна вещь, которую я не понял, заключалась в том, что использование "with ur" в конце моих операторов select не помогло устранить взаимоблокировки по сравнению с "with cs", который я сейчас использую. У Wonder есть уровень изоляции базы данных, который 'rs' должен с этим что-то делать?

Поскольку вы выполняете несколько вставок, обновлений, удалений, я хотел бы предложить вам добавить

<property name="hibernate.connection.autocommit" value="false"/>

И как только все ваши запросы будут выполнены успешно, сделайте коммит вручную connection.commit();Может быть, это может помочь вам.

Другие вопросы по тегам