2

Spring 트랜잭션 관리를 사용하여 최대 절전 모드로 애플리케이션을 제어하고 스레드의 두 인스턴스를 사용하여 동시성 데이터베이스에 액세스하고 하나의 테이블을 수정합니다. 값이 보존되도록 보장합니다. 표는 이전입니다 :isolation_serializable을 사용하여 Spring과 hibernate를 이용한 트랜잭션 관리

quantidade_livro_id | quantidade | livro_id | tt 
    ---------------------+------------+----------+---- 
        7 |  100 |  3 | as 
        5 |  100 |  1 | as 
        6 |  100 |  2 | as 

그리고 테이블 후 :

 Servico t1 = new Servico(); 
     Servico t2 = new Servico(); 
     //transaction 1 
     t1.setId1(5); 
     t1.setValorTransacao(50); 
     t1.setId2(6); 
     //transaction 2  
     t2.setId1(5); 
     t2.setValorTransacao(100); 
     t2.setId2(7); 

     //start transaction 1 
     t1.start(); 
     //start transaction 2 
     t2.start(); 

클래스 Servico은 다음과 같습니다 :

public void run() { 
     executa(); 
    } 


public void executa(){ 
    ApplicationContext appContext = 
      new ClassPathXmlApplicationContext("spring/config/BeanLocations.xml"); 

    livroQuantidadeBo = (LivroQuantBo)appContext.getBean("livroQuantBoProxy"); 
    try { 
     livroQuantidadeBo.transacao(getId1(),getValorTransacao(),getId2()); 
    } catch (RuntimeException e) { 
     // TODO Auto-generated catch block 
     System.out.println(e); 
    } 

quantidade_livro_id | quantidade | livro_id | tt 
    ---------------------+------------+----------+---- 
       7 |  100 |  3 | as 
       5 |   50 |  1 | as 
       6 |  150 |  2 | as 

주요 코드는 두 개의 스레드를 시작합니다

클래스 LivroQuantBoImpl는 방법이 있습니다

public void transacao(int id1,int valorTransferencia, int id2) throws RuntimeException{ 
    LivroQuantidade livroQ = livroQuantDao.find(id1); 
    LivroQuantidade livroQ2 = livroQuantDao.find(id2); 
    if(livroQ.getQuantidade() - valorTransferencia >= 0){ 
     livroQ.setQuantidade(livroQ.getQuantidade() - valorTransferencia); 
     livroQ2.setQuantidade(valorTransferencia + livroQ2.getQuantidade()); 
     livroQuantDao.update(livroQ); 
     livroQuantDao.update(livroQ2); 
    } 
} 

을 그리고 내 봄의 .conf은 다음과 같습니다

<!-- DATASOURCE --> 
    <bean 
    class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> 
     <property name="location"> 
      <value>properties/database.properties</value> 
     </property> 
    </bean> 

    <bean id="dataSource" 
      class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
     <property name="driverClassName" value="${jdbc.driverClassName}" /> 
     <property name="url" value="${jdbc.url}" /> 
     <property name="username" value="${jdbc.username}" /> 
     <property name="password" value="${jdbc.password}" /> 
    </bean> 


    <!-- HIBERNATE --> 

    <!-- Hibernate session factory --> 
    <bean id="sessionFactory" 
     class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> 

     <property name="dataSource"> 
      <ref bean="dataSource"/> 
     </property> 

     <property name="hibernateProperties"> 
      <props> 
      <prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop> 
      <prop key="hibernate.show_sql">true</prop> 
      </props> 
     </property> 

     <property name="mappingResources"> 
     <list> 
       <value>hibernate/Livro.hbm.xml</value> 
       <value>hibernate/LivroQuantidade.hbm.xml</value> 
     </list> 
      </property> 

     </bean> 

    <!-- TRANSAÇÃO --> 

    <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor"> 
     <property name="transactionManager" ref="transactionManager" /> 
     <property name="transactionAttributes"> 
     <props> 
     <prop key="save">PROPAGATION_REQUIRED</prop> 
     <prop key="transacao">PROPAGATION_REQUIRED</prop> 
     <prop key="transacao">ISOLATION_SERIALIZABLE</prop> 
     </props> 
     </property> 
    </bean> 

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


    <!-- BEANS --> 
     <!-- Livro business object --> 
     <bean id="livroBo" class="br.com.spring.bo.LivroBoImpl" > 
      <property name="livroDao" ref="livroDao" /> 
      <property name="livroQuantBo" ref="livroQuantBo" /> 
     </bean> 

     <!-- Livro Data Access Object --> 
     <bean id="livroDao" class="br.com.spring.dao.LivroDaoImpl" > 
      <property name="sessionFactory" ref="sessionFactory"></property> 
     </bean> 

     <!-- ProductQoh business object --> 
     <bean id="livroQuantBo" class="br.com.spring.bo.LivroQuantBoImpl" > 
      <property name="livroQuantDao" ref="livroQuantDao" /> 
     </bean> 

     <!-- ProductQoh Data Access Object --> 
     <bean id="livroQuantDao" class="br.com.spring.dao.LivroQuantDaoImpl" > 
      <property name="sessionFactory" ref="sessionFactory"></property> 
     </bean> 

    <!-- PROXY --> 

     <bean id="livroBoProxy" 
      class="org.springframework.aop.framework.ProxyFactoryBean"> 
      <property name="target" ref="livroBo" /> 
      <property name="interceptorNames"> 
       <list> 
        <value>transactionInterceptor</value> 
       </list> 
      </property> 
     </bean> 

     <bean id="livroQuantBoProxy" 
      class="org.springframework.aop.framework.ProxyFactoryBean"> 
      <property name="target" ref="livroQuantBo" /> 
      <property name="interceptorNames"> 
       <list> 
        <value>transactionInterceptor</value> 
       </list> 
      </property> 
     </bean> 

그리고이 런타임 예외하고있어 :

Hibernate: select livroquant0_.quantidade_livro_id as quantidade1_2_, livroquant0_.quantidade as quantidade2_, livroquant0_.livro_id as livro3_2_ from springhibernate2.quantidadeLivro livroquant0_ where livroquant0_.quantidade_livro_id=? 
Hibernate: select livroquant0_.quantidade_livro_id as quantidade1_3_, livroquant0_.quantidade as quantidade3_, livroquant0_.livro_id as livro3_3_ from springhibernate2.quantidadeLivro livroquant0_ where livroquant0_.quantidade_livro_id=? 
Hibernate: select livroquant0_.quantidade_livro_id as quantidade1_3_, livroquant0_.quantidade as quantidade3_, livroquant0_.livro_id as livro3_3_ from springhibernate2.quantidadeLivro livroquant0_ where livroquant0_.quantidade_livro_id=? 
Hibernate: select livroquant0_.quantidade_livro_id as quantidade1_2_, livroquant0_.quantidade as quantidade2_, livroquant0_.livro_id as livro3_2_ from springhibernate2.quantidadeLivro livroquant0_ where livroquant0_.quantidade_livro_id=? 
Hibernate: update springhibernate2.quantidadeLivro set quantidade=?, livro_id=? where quantidade_livro_id=? 
Hibernate: update springhibernate2.quantidadeLivro set quantidade=?, livro_id=? where quantidade_livro_id=? 
Hibernate: update springhibernate2.quantidadeLivro set quantidade=?, livro_id=? where quantidade_livro_id=? 
Hibernate: update springhibernate2.quantidadeLivro set quantidade=?, livro_id=? where quantidade_livro_id=? 
Nov 6, 2012 3:02:49 PM org.hibernate.util.JDBCExceptionReporter logExceptions 
WARNING: SQL Error: 0, SQLState: 40001 
Nov 6, 2012 3:02:49 PM org.hibernate.util.JDBCExceptionReporter logExceptions 
SEVERE: Batch entry 0 update springhibernate2.quantidadeLivro set quantidade='0', livro_id='1' where quantidade_livro_id='5' was aborted. Call getNextException to see the cause. 
Nov 6, 2012 3:02:49 PM org.hibernate.util.JDBCExceptionReporter logExceptions 
WARNING: SQL Error: 0, SQLState: 40001 
Nov 6, 2012 3:02:49 PM org.hibernate.util.JDBCExceptionReporter logExceptions 
SEVERE: ERROR: could not serialize access due to concurrent update 
Nov 6, 2012 3:02:49 PM org.hibernate.event.def.AbstractFlushingEventListener performExecutions 
SEVERE: Could not synchronize database state with session 
org.hibernate.exception.LockAcquisitionException: Could not execute JDBC batch update 
    at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:82) 
    at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43) 
    at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:254) 
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:237) 
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:142) 
    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.JDBCTransaction.commit(JDBCTransaction.java:106) 
    at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:656) 
    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 $Proxy0.transacao(Unknown Source) 
    at br.com.spring.service.Servico.executa(Servico.java:29) 
    at br.com.spring.service.Servico.run(Servico.java:19) 
    Caused by: java.sql.BatchUpdateException: Batch entry 0 update springhibernate2.quantidadeLivro set quantidade='0', livro_id='1' where quantidade_livro_id='5' was aborted. Call getNextException to see the cause. 
at org.postgresql.jdbc2.AbstractJdbc2Statement$BatchResultHandler.handleError(AbstractJdbc2Statement.java:2621) 
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1837) 
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:407) 
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeBatch(AbstractJdbc2Statement.java:2754) 
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:48) 
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:247) 
... 17 more 
    org.springframework.dao.CannotAcquireLockException: Could not execute JDBC batch update; SQL [update springhibernate2.quantidadeLivro set quantidade=?, livro_id=? where quantidade_livro_id=?]; nested exception is org.hibernate.exception.LockAcquisitionException: Could not execute JDBC batch update 

잘못 무엇입니까?

답변

관련 문제