ååãJPAã®ãããžã§ã¯ã·ã§ã³ã䜿ã£ãŠå¹ççã«ããŒã¿ã®äžéšãååŸãããã¯ããã¯ãåŠã³ãŸãããããã§ãããŒã¿ã®å ¥åºåã«é¢ããç¥èã¯ã»ãŒå®ç§ã§ãã
ä»åã¯ãæ¥åã·ã¹ãã ã®ä¿¡é Œæ§ãç¹ã«ããŒã¿ããŒã¹æäœã®ä¿¡é Œæ§ãä¿èšŒããããã®éåžžã«éèŠãªæŠå¿µã§ããããã©ã³ã¶ã¯ã·ã§ã³ç®¡çãã«ã€ããŠåŠã³ãŸãã
ãã©ã³ã¶ã¯ã·ã§ã³ã¯ãè€æ°ã®ããŒã¿ããŒã¹æäœãäžã€ã®ãŸãšãŸããšããŠæ±ããããŒã¿ã®äžè²«æ§ãšæŽåæ§ãå®ãããã®ä»çµã¿ã§ãã
1. ãã©ã³ã¶ã¯ã·ã§ã³ãšã¯äœãïŒ
**ãã©ã³ã¶ã¯ã·ã§ã³ïŒTransactionïŒãšã¯ãäžé£ã®äžå¯åïŒAtomicïŒ**ãªããŒã¿ããŒã¹æäœã®ããšã§ãã
äŸãã°ããéè¡å£åº§Aãã10,000åãåŒãåºããå£åº§Bã«10,000åãæ¯ã蟌ãããšããåŠçãèããŸãããã®åŠçã¯ã以äžã®2ã€ã®DBæäœããæãç«ã£ãŠããŸãã
- å£åº§Aã®æ®é«ãæžããïŒUPDATEïŒ
- å£åº§Bã®æ®é«ãå¢ããïŒUPDATEïŒ
ããã1ãæåããçŽåŸã«ã·ã¹ãã é害ãçºçãã2ãå®è¡ãããªãã£ããã©ããªãã§ããããïŒå£åº§Aããã¯ãéãæžã£ãã®ã«ãå£åº§Bã«ã¯å¢ããããéãæ¶æ» ããŠããŸããŸãã
ãã©ã³ã¶ã¯ã·ã§ã³ã¯ããã®ãããªäºæ ãé²ãã2ã€ã®æäœãå¿ ãäž¡æ¹æåãããããããã¯äž¡æ¹å€±æããããšãä¿èšŒããŸãã
ãã©ã³ã¶ã¯ã·ã§ã³ã®4ã€ã®ç¹æ§ïŒACIDç¹æ§ïŒ
ãã©ã³ã¶ã¯ã·ã§ã³ã¯ã以äžã®4ã€ã®ç¹æ§ïŒACIDç¹æ§ïŒãæºããå¿ èŠããããŸãã
| ç¹æ§ | æå³ | è£è¶³ |
| AtomicityïŒååæ§ïŒ | å šãŠã®æäœãæåããããå šãŠå€±æããŠå ã«æ»ãïŒRollbackïŒã | ãå šéšããããå šããããªããããä¿èšŒã |
| ConsistencyïŒäžè²«æ§ïŒ | ãã©ã³ã¶ã¯ã·ã§ã³ã®éå§åãšçµäºåŸã§ãããŒã¿ã®æŽåæ§ãä¿ãããã | ççŸããç¶æ ã«ãªããªãããšãä¿èšŒã |
| IsolationïŒé颿§ïŒ | è€æ°ã®ãã©ã³ã¶ã¯ã·ã§ã³ãåæã«å®è¡ãããŠããäºãã«åœ±é¿ãäžããªãã | åŠçã¯æä»çã«è¡ãããïŒåæå®è¡å¶åŸ¡ïŒã |
| DurabilityïŒæ°žç¶æ§ïŒ | ãã©ã³ã¶ã¯ã·ã§ã³ãæåïŒCommitïŒãããããã®çµæã¯æ°žç¶çã«ä¿æãããã | DBã«ç©ççã«æžã蟌ãŸããããšãä¿èšŒã |
2. Springã«ããããã©ã³ã¶ã¯ã·ã§ã³ç®¡ç
åŸæ¥ã®Javaéçºã§ã¯ããã©ã³ã¶ã¯ã·ã§ã³ã®éå§ïŒbegin()ïŒãšçµäºïŒcommit()/rollback()ïŒããéçºè
ãæåã§ã³ãŒãã«èšè¿°ããå¿
èŠããããŸããã
Spring Frameworkã§ã¯ããã®é¢åãªãã©ã³ã¶ã¯ã·ã§ã³å¶åŸ¡ãã宣èšçã«ãã€ãŸãã¢ãããŒã·ã§ã³ãä»ããã ãã§å®çŸã§ããŸãã
@Transactional ã¢ãããŒã·ã§ã³
Springã§ãã©ã³ã¶ã¯ã·ã§ã³ç®¡çãè¡ãäžå¿çãªã¢ãããŒã·ã§ã³ã @Transactional ã§ãã
ãã®ã¢ãããŒã·ã§ã³ãServiceå±€ã®ã¯ã©ã¹å šäœããŸãã¯ç¹å®ã®ã¡ãœããã«ä»äžããŸãã
Java
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import lombok.RequiredArgsConstructor;
// Serviceå±€ã®ã¯ã©ã¹å
šäœã« @Transactional ãä»äžããã±ãŒã¹ãå€ã
@Service
@Transactional
@RequiredArgsConstructor
public class TransferService {
private final AccountRepository accountRepository;
// ãã®ã¡ãœããå
ã®è€æ°ã®DBæäœããäžã€ã®ãã©ã³ã¶ã¯ã·ã§ã³ãšããŠæ±ããã
public void transfer(Long fromId, Long toId, int amount) {
// 1. å£åº§AããåŒãåºã
Account fromAccount = accountRepository.findById(fromId).orElseThrow();
fromAccount.setBalance(fromAccount.getBalance() - amount);
accountRepository.save(fromAccount); // DBæäœâ
// ãã·ã¹ãã ãšã©ãŒãã©ã³ã¿ã€ã äŸå€ãçºçããå Žåãæ³å®ã
if (amount > 100000) {
// RuntimeException (å®è¡æäŸå€)ãã¹ããŒ
throw new IllegalArgumentException("äžåã®æ¯ã蟌ã¿é¡ãäžéãè¶
ããŠããŸã");
}
// 2. å£åº§Bãžå
¥é
Account toAccount = accountRepository.findById(toId).orElseThrow();
toAccount.setBalance(toAccount.getBalance() + amount);
accountRepository.save(toAccount); // DBæäœâ¡
// 3. äŸå€ãçºçããªããã°ãèªåçã«ã³ããã(Commit)ããã
}
// ã¡ãœãããæ£åžžçµäºããå Žå -> ã³ããã
// RuntimeExceptionãçºçããå Žå -> ããŒã«ããã¯(Rollback)
}
3. ãã©ã³ã¶ã¯ã·ã§ã³ã®èªåå¶åŸ¡
@Transactional ãä»äžãããã¡ãœãããå®è¡ããããšãSpringã¯ä»¥äžã®å¶åŸ¡ãèªåã§è¡ããŸãã
- éå§: ã¡ãœãããåŒã³åºãããåã«ããã©ã³ã¶ã¯ã·ã§ã³ãéå§ããŸãã
- å®è¡: ã¡ãœããå ã®å šãŠã®DBæäœãå®è¡ããŸãã
- ã³ããã: ã¡ãœãããæ£åžžã«çµäºããå Žåãå šãŠã®å€æŽãDBã«æ°žç¶çã«åæ ïŒCommitïŒããŸãã
- ããŒã«ããã¯: ã¡ãœããå®è¡äžã«
RuntimeExceptionïŒå®è¡æäŸå€ïŒ ãŸãã¯Errorãçºçããå ŽåããããŸã§ã«å®è¡ãããå šãŠã®DBæäœãåãæ¶ãïŒRollbackïŒãããŒã¿éå§åã®ç¶æ ã«æ»ããŸãã
ãã€ã³ã:
@Transactionalã¯ãããã©ã«ãã§ãã§ãã¯äŸå€ïŒChecked ExceptionïŒïŒäŸ:IOExceptionïŒãçºçããå Žåã¯ããŒã«ããã¯ããŸãããããŒã«ããã¯ããããå Žåã¯ã@Transactional(rollbackFor = Exception.class)ã®ããã«æç€ºçã«èšå®ããå¿ èŠããããŸãã
4. èªã¿åãå°çšãã©ã³ã¶ã¯ã·ã§ã³
ããŒã¿ã倿Žãããåã«DBããèªã¿åãã ãã®ã¡ãœããïŒäŸ: findByIdãfindAllïŒã«ã¯ãreadOnly 屿§ãæå®ããã®ããã¹ããã©ã¯ãã£ã¹ã§ãã
Java
@Service
@Transactional(readOnly = true) // ã¯ã©ã¹å
šäœãèªã¿åãå°çšã«èšå®
public class ItemService {
// ããŒã¿å€æŽãè¡ãã¡ãœããã®ã¿ãåå¥ã«äžæžã
@Transactional(readOnly = false) // ãŸãã¯åã« @Transactional
public Item saveItem(Item item) {
// ... ä¿ååŠç
}
// èªã¿åãå°çšã®ã¡ãœããïŒé«éåãšDBãªãœãŒã¹ã®ç¯çŽã«è²¢ç®ïŒ
// ã¯ã©ã¹èšå®ã«ãã readOnly = true ãé©çšããã
public List<Item> findAllItems() {
// ... æ€çŽ¢åŠç
}
}
readOnly = true ã«èšå®ããããšã§ãDBåŽã§ãæé©åïŒããã¯ã®çç¥ãªã©ïŒãè¡ãããããã©ãŒãã³ã¹ãåäžããDBãªãœãŒã¹ã®ç¯çŽã«ç¹ãããŸãã
â æ¬æ¥ã®ãŸãšã
- ãã©ã³ã¶ã¯ã·ã§ã³ã¯ãè€æ°ã®DBæäœãäžå¯åãªäžã€ã®åäœãšããŠæ±ããACIDç¹æ§ïŒååæ§ãäžè²«æ§ãé颿§ãæ°žç¶æ§ïŒãä¿èšŒããã
- Springã§ã¯ã
@Transactionalã¢ãããŒã·ã§ã³ãServiceå±€ã®ã¡ãœããã«ä»ããããšã§ããã©ã³ã¶ã¯ã·ã§ã³ã®éå§ãã³ããããããŒã«ããã¯ã宣èšçã«èªå管çã§ããã - ããã©ã«ãã§ã¯ã
RuntimeExceptionã®ã¿ããŒã«ããã¯ã®å¯Ÿè±¡ãšãªãã - ããŒã¿ã®èªã¿åãã®ã¿ãè¡ãã¡ãœããã«ã¯ã
@Transactional(readOnly = true)ãèšå®ããããã©ãŒãã³ã¹ãåäžãããã
ð æ¬¡åäºå
ãã©ã³ã¶ã¯ã·ã§ã³ç®¡çãèŠããããšã§ãæ¥ååŠçã®ä¿¡é Œæ§ã¯æ Œæ®µã«åäžããŸãããããããã·ã¹ãã ã倧ãããªããšãåæã«è€æ°ã®ãŠãŒã¶ãŒãåãããŒã¿ã«ã¢ã¯ã»ã¹ãã䞊è¡åŠçã®åé¡ãåºãŠããŸãã
次åã¯ããã©ã³ã¶ã¯ã·ã§ã³ã®éé¢ã¬ãã«ïŒIsolation LevelïŒãšããæŠå¿µãåŠã³ãåæå®è¡æã®ããŒã¿ã®ç«¶åïŒã³ã³ããªã¯ãïŒãã©ã®ããã«é²ããã«ã€ããŠæ·±ãçè§£ããŸãã
次åïŒã第27åããã©ã³ã¶ã¯ã·ã§ã³ã®éé¢ã¬ãã«ãšäžŠè¡åŠç ã«ãæåŸ ãã ããïŒ


ã³ã¡ã³ã