트랜잭션 : 데이터베이스에서 데이터에 대한 하나의 논리적 실행단계
ACID (원자성, 일관성, 고립성, 지속성)는 데이터베이스 트랜잭션이 안전하게 수행된다는 것을 보장하기 위한 성질을 가리키는 약어
출처: 위키백과
트랜잭션 시작
모두 성공 시 ⇒트랜잭션 Commit
중간에 하나라도 실패 시 ⇒ 트랜잭션 Rollback
public List<Folder> addFolders(List<String> folderNames, User user) {
// 트랜잭션의 시작
TransactionStatus status = this.transactionManager.getTransaction(new DefaultTransactionDefinition());
try {
// 1) 입력으로 들어온 폴더 이름을 기준으로, 회원이 이미 생성한 폴더들을 조회합니다.
List<Folder> existFolderList = folderRepository.findAllByUserAndNameIn(user, folderNames);
List<Folder> savedFolderList = new ArrayList<>();
for (String folderName : folderNames) {
// 2) 이미 생성한 폴더가 아닌 경우만 폴더 생성
if (isExistFolderName(folderName, existFolderList)) {
// Exception 발생!
throw new IllegalArgumentException("중복된 폴더명을 제거해 주세요! 폴더명: " + folderName);
} else {
Folder folder = new Folder(folderName, user);
// 폴더명 저장
folder = folderRepository.save(folder);
savedFolderList.add(folder);
}
}
// 트랜잭션 commit
transactionManager.commit(status);
return savedFolderList;
} catch (Exception ex) {
// 트랜잭션 rollback
transactionManager.rollback(status);
throw ex;
}
}
Service에서 DB한테 트랜잭션 시작을 알려준다. 그럼 DB에서 트랜잭션 Id를 부여해주고 그 Id를 가지고 커밋하거나 롤백을 하는 흐름이다.
구조를 보니 전에 공부했던 AOP 구조와 거의 흡사하다.
그렇다. @Transactional은 AOP가 동작하는 것이다.
@Transactional
public List<Folder> addFolders(List<String> folderNames, User user) {
// ...
}
쓰기 전용 DB (Primary) 와 읽기 전용 DB (Replica) 를 구분
@Transactional(**readOnly = false**)
import org.springframework.transaction.annotation.Transactional;
@Transactional
public List<Folder> createFolders(List<String> folderNameList, User user) {
@Transactional(**readOnly = true**)
Replica 중 1개가 Primary 로 승격 됨
다시 Primary - Replica 로 정상 운영