2013-10-24 3 views
0

Spring @Transaction으로 어떤 주석을 달 것인지 결정하는 방법을 이해하는 데 어려움을 겪고 있습니다. 전송 내 Spring @Transaction

BankService { 

    transfer(Account from, Account to, int amount){ 
     deduct(from, amount); 
     deposit(to, amount); 
    } 

    deduct(Account account, int amount){ 
     account = accountRepo.load(account); //make sure we dont have an old reference with old balance    
     int balance = account.getBalance(); 
     if (balance<amount){ 
      throw new IllegalStateException("Not enough money"); 
     } else { 
      account.setBalance(balance-amount); 
      accountRepo.save(account); 
     } 
    } 

    deposit(Account account, int amount){ 
     account = accountRepo.load(account); //make sure we dont have an old reference with old balance 
     account.setBalance(account.getBalance() + amount); 
     accountRepo.save(account); 
    } 

} 

의 공제가 실패 할 경우에도 실패 나던 보증금 경우, 분명히 보증금은 이 지속되어서는 안된다.

5 가지 방법 (전송, 차감, 입금,로드, 저장) 중에서 @Transactional로 주석을 달아야하는 이유와 그 이유는 무엇입니까?

+1

가능한 가장 유용한 예외를 던집니다. 이 경우 계정이 과도하게 사용 된 경우 IllegalStateException은 일반 'RuntimeException'보다 설명 적입니다. – chrylis

+0

나는 이것이 http://javaidm.blogspot.in/2016/02/how-transaction-is-managed-in-spring.html에 도움이된다고 생각한다. –

답변

0

2+ 속성을 수정하는 모든 메서드는 @Transactional이어야합니다. 나는 당신에게 예금으로 돈을 송금하는 방법을 당신에게주지 않았습니다. 실제 트랜잭션을 정의하는 작업

+1

나는 그 속성이 수정되지는 않았지만 본성 메서드가 @Transactional로 주석을 달아야하는지 여부를 결정하는 수행 된 작업 중 하나입니다. – fred

+0

데이터베이스에서 어떤 일이 일어나는지 생각하십시오. 2 가지 이상을 변경해야합니까? 한 번 실패하면 롤백해야합니까? 이를 알면 Transactional 메소드를 쉽게 볼 수 있습니다. –

+0

물론, 단일 실패로 롤백해야합니다. 격리 수준, 특히 반복 읽기에 대해 알아야합니다. – chrylis

3

일반적인 대답

봐 -이 경우에는 transfer 방법. 이 방법은 그 자체로 완전한 트랜잭션을 나타내고, 그래서 당신은 당신이 잘못 트랜잭션에서 호출되는 다른 방법을 보호해야하고, 그래서 좋은 생각이 그들에게

에 주석의 그것을

@Transactional(propagation = REQUIRED) 

을 표시해야

@Transactional(propagation = MANDATORY) 

실행중인 트랜잭션의 컨텍스트에서만 호출되도록합니다.

하지 않는, 암시 적 또는 명시 적으로, 봄 고유의 대답은 기본적으로

, 봄은 이러한 거래로 조언을 구현하는 프록시 객체를 사용하고, 자기 호출 (방법은 this에 호출 프록시 객체를 통해) advice가 적용되지 않는다. 이것은 Spring이이 경우에 실제로 deductdeposit 메소드에 대한 조언을 강요하지 않는다는 것을 의미한다.하지만 다른 메소드에 의해 트랜잭션 외부에서 호출되지 않도록 보호한다. AspectJ AOP 모델은 추가적인 컴파일 타임 단계가 필요하지만 자체 호출 문제를 피하고 모든 메소드 호출에 조언을 올바르게 적용한다.

+0

그래서 전송 메소드에는 @Tr ... (propagation = REQUIRED) 및 * all *로 주석을 달고 나머지 4 개의 메소드에는 @ (Tr ... propagation = MANDATORY) 주석을 달아야합니까? 어떤 사람들 (http://stackoverflow.com/a/15300683/794779 참조)은 CRUD 메소드에 @Transactional을 주석으로 추가해서는 안된다고 말합니다.또한 공제 및 입금 방법에 주석을 달았지 만 적용하지 않으면 문제가 발생하지 않습니까? 논리적으로 주석이 달린 메서드는 강제로 적용될 예정입니까? – fred

+1

@fred 링크 된 대답은 기껏해야 불완전합니다. 저자는 무작위 CRUD 방법으로 거래가 열리는 것을 허용해서는 안된다는 말을하고 있는데 이는 정확합니다. 'MANDATORY'는 메소드가 트랜잭션을 처리하는 것이 아니라 트랜잭션 외부에서 호출되는 경우 예외를 throw하도록 Spring에 지시합니다. Spring 프록시 AOP (비록 그렇지 않다)를 사용하더라도,'MANDATORY' (1)을 사용하는 것은 문서화 역할을하고 (2) 외부 클래스의''deduct' 호출을 직접 보호 할 수 있습니다. – chrylis

+1

@fred 또한'load'와'save'를 게시하지 않았으며, 그들이하는 일이 무엇인지 분명하지 않습니다. 나는 단지'transfer','deposit','deduct'에 대해서만 이야기하고 있습니다. – chrylis

관련 문제