2014-02-09 1 views
1

Spring 격리를 테스트하는 매우 간단한 예를 만들고 있습니다. ,Spring 트랜잭션 격리가 작동하지 않음

@Service("service1") 
@Transactional 
public class Service1 { 

    private UserService userService; 

    private static Logger log = Logger.getLogger(Service1.class); 

    public void changeCredits() {  
     User user = userService.getUserById(1); 

     log.info("Service1 previous credits: " + user.getCredits()); 
     int newCredit = user.getCredits() + 5; 
     user.setCredits(newCredit); 

     log.info("Service1 new credits: " + user.getCredits()); 
    } 
... 

@Service("service2") 
@Transactional 
public class Service2 { 

    private UserService userService; 

    private static Logger log = Logger.getLogger(Service2.class); 

    public void changeCredits() { 

     User user = userService.getUserById(1); 

     log.info("Service2 previous credits: " + user.getCredits()); 
     int newCredit = user.getCredits() + 5; 
     user.setCredits(newCredit); 

     log.info("Service2 new credits: " + user.getCredits()); 
    } 

이 코드를 실행 한 후, 나는 두 트랜잭션이 동시에 실행된다는 점을 때 볼 수 있습니다 : 나는이 개 매우 유사한 서비스 클래스를 가지고, 또한

@Service("manager1") 
public class Manager1 { 

    private Service1 service1; 

    @Scheduled(fixedDelay = 15000) 
    public void sendScheduledCampaigns() { 
     service1.changeCredits(); 
    } 
... 

@Service("manager2") 
public class Manager2 { 

    private Service2 service2; 

    @Scheduled(fixedDelay = 15000) 
    public void sendScheduledCampaigns() { 
     service2.changeCredits(); 
    } 
... 

: 나는이 개 매우 비슷한 일정의 수업을 두 트랜잭션 모두 데이터베이스에서 동일한 값을 얻고 있습니다. 그래서, 그들은 다른 하나의 수정을 무시하고 있습니다. 나는이 트랜잭션 격리에 오류가 가정 : 여기

INFO 27 Feb 2014 14:14:22 - Service1 previous credits: 0 
INFO 27 Feb 2014 14:14:22 - Service2 previous credits: 0 
INFO 27 Feb 2014 14:14:22 - Service1 new credits: 5 
INFO 27 Feb 2014 14:14:22 - Service2 new credits: 5 

크레딧 값이 10해야한다.

Feb 27, 2014 2:14:23 PM org.apache.coyote.AbstractProtocol start 
INFO: Starting ProtocolHandler ["http-bio-8080"] 
Feb 27, 2014 2:14:23 PM org.apache.coyote.AbstractProtocol start 
INFO: Starting ProtocolHandler ["ajp-bio-8009"] 
Feb 27, 2014 2:14:23 PM org.apache.catalina.startup.Catalina start 
INFO: Server startup in 10698 ms 
INFO 27 Feb 2014 14:14:37 - Service2 previous credits: 5 
INFO 27 Feb 2014 14:14:37 - Service2 new credits: 10 
INFO 27 Feb 2014 14:14:38 - Service1 previous credits: 10 
INFO 27 Feb 2014 14:14:38 - Service1 new credits: 15 

내가 MYSQL 함께 일하고 있어요 이러한 나의 작업 및 거래의 구성은 다음과 같습니다 :

<task:annotation-driven executor="myExecutor" scheduler="myScheduler"/> 
<task:executor id="myExecutor" pool-size="100"/> 
<task:scheduler id="myScheduler" pool-size="100"/> 

<tx:annotation-driven transaction-manager="transactionManager"/> 

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

<bean id="sessionFactory" 
    class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> 
    <property name="dataSource" ref="myDataSource" /> 
    <property name="hibernateProperties"> 
     <props> 
      <prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop> 
      <prop key="hibernate.show_sql">false</prop> 
     </props> 
    </property> 
    <property name="packagesToScan" value="test.domain" /> 
</bean> 
이 후

, 두 프로세스가 동시에 실행되지 않습니다으로는, 계산은 정상적인 것으로 시작

내 기본 격리 수준은 null입니다. 나는이에서 그것을 가지고 :

log.info("isolation: " +TransactionSynchronizationManager.getCurrentTransactionIsolationLevel()); 

그래서, 두 서비스의 분리 레벨을 변경하려고 :

@Service("service1") 
@Transactional(isolation=Isolation.REPEATABLE_READ) 
public class Service1 { 

@Service("service2") 
@Transactional(isolation=Isolation.REPEATABLE_READ) 
public class Service2 { 

결과는 여전히 잘못된 것입니다.

왜 이런 일이 발생했는지 알고 계십니까?

미리 감사드립니다.

답변

1

이 경우 @ 트랜잭션은 사용중인 데이터베이스에 따라 달라지는 기본 격리를 사용하고, 격리 특성을 사용하고 Isolation.REPEATABLE_READ를 사용하여 원하는 동작을 얻으려고합니다.

열거 (단열)를 TransactionDefinition 인터페이스에 대응하는 트랜잭션 격리에게 트랜잭션 주석과 함께 사용 열거 수준을 나타낸다.

http://docs.spring.io/spring/docs/3.2.x/javadoc-api/org/springframework/transaction/annotation/Isolation.html#DEFAULT

트랜잭션이 실행중인 다른 트랜잭션에서 수정하고 아직 커밋하지 된 행에서 데이터를 읽을 수 때 더러운 읽기가 발생

.

+0

안녕하세요 Koitoer, 답변 해 주셔서 감사합니다. 저는 트랜잭션의 격리 수준을 변경하려고했습니다. 그러나 결과는 완전히 동일합니다. @Transactional (격리 = Isolation.REPEATABLE_READ) 다른 생각 :이 작업을 수행하는 , 나는 두 서비스에서 트랜잭션 주석에 "분리 속성"을 추가? 다시 한 번 감사드립니다. –

+0

어제 밤에 어제 밤에 thining하고 PessimisticLock과 같은 객체에서 잠금 기능을 사용했지만 객체를 검색하는 방법에 대해 확신하지 못했습니다. DAO에서 find 메소드를 사용하면 코드를 붙여 넣을 수 있습니다. 엔티티 관리자를 사용하는 경우에도 잠금 옵션과 함께 find를 사용해보십시오. – Koitoer

+0

@GonzaloRon 이상하게도 같은 문제가 발생합니다. 모두 SERIALIZABLE로 설정했으며 spring jdbc와 함께 Postgres를 사용하고 있습니다. – deFreitas

관련 문제