Java에서 트랜잭션(Transaction)은 데이터베이스 상태를 관리하기 위한 중요한 개념이다. 트랜잭션은 여러 작업을 하나의 논리적인 작업 단위로 묶어주며, 모든 작업이 성공해야지만 전체 작업이 커밋(commit)되고, 중간에 하나라도 실패하면 롤백하여 데이터의 일관성을 유지한다.
1. 트랜잭션의 ACID 속성
- 원자성(Atomicity) : 트랜잭션 내 모든 작업이 하나의 단위로 실행되어야 하며, 일부만 성공하거나 실패해서는 안된다. 즉, 증간에 오류가 발생하면 트랜잭션 전체가 롤백된다.
- 일관성(Consistency) : 트랜잭션이 완료되면 데이터베이스가 일관된 상태를 유지해야 한다.
- 고립성(Isolation) : 트랜잭션 간 서로 독립적으로 실행되며, 트랜잭션이 완료되기 전까지 다른 트랜잭션이 중간 상태를 참조하지 않도록 보장한다.
- 내구성(Durability) : 트랜잭션이 성공적으로 완료되면 결과가 영구적으로 저장된다.
2. 프로그래밍 방식으로 트랜잭션 관리하기
트랜잭션을 프로그래밍 방식으로 관리하는 것은 @Transactional 과 같은 선언전 트랜잭션 방식이 아닌, 코드 내에서 직접 트랜잭션을 시작하고 커밋하거나 롤백하는 방식을 말한다.
이는 주로 Spring의 TransactionTemplate 또는 PlatformTransactionManager 를 사용하여 트랜잭션을 명시적으로 관리하는 방법이다.
프로그래밍적 방식은 코드에서 트랜잭션을 더 세밀하게 제어해야할 때 유용하다. 트랜잭션의 범위, 시작 및 종료 조건을 코드로 지정할 수 있어 복잡한 트랜잭션 관리가 필요할 때 적합하다.
1. TransactionTemplate 이용하기
TransactionTemplate 은 Spring에서 제공하는 트랜잭션 관리 도구로, 간단한 트랜잭션 작업을 수행하기에 적합하다. TransactionTemplate 을 사용하면 트랜잭션 범위를 람다나 익명 클래스에서 지정할 수 있다.
@Service
@RequiredArgsConstructor
public class ExampleService {
private final TransactionTemplate transactionTemplate;
public void exampleMethod() {
transactionTemplate.execute(status -> {
try {
// 트랜잭션 내에서 수행할 작업
insertDatabase();
// 필요시 커밋하기 전에 특정 조건을 검토하고 롤백 가능
if (condition) {
status.setRollbackOnly(); // 트랜잭션 롤백
}
} catch (Exception e) {
status.setRollbackOnly(); // 예외 발생 시 롤백 설정
}
return null;
})
}
private void insertDatabase() {
// 트랜잭션으로 보호할 작업 수행
}
}
- transactionTemplate.execute() 메서드는 트랜잭션을 시작하고, 내부 코드가 완료되면 자동으로 커밋한다.
- status.setRollbackOnly() 를 호출하면 트랜잭션이 롤백 된다.
2. PlatformTransactionManager 이용하기
PlatformTransactionManager 를 직접 사용하면 트랜잭션을 더욱 세밀하게 관리할 수 있다. Spring에서 제공하는 PlatformTransactionManager 인터페이스는 트랜잭션을 시작하고 커밋하거나 롤백하는 메서드를 제공한다.
@Service
@RequiredArgsConstructor
public class ExampleService {
private final PlatformTransactionManager transactionManager;
public void exampleMethod() {
TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());
try {
// 트랜잭션 내에서 수행할 작업
insertDatabase();
transactionManager.commit(status); // 성공 시 커밋
} catch (Exception e) {
transactionManager.rollback(status); // 예외 발생 시 롤백
}
}
private void insertDatabase() {
// 트랜잭션으로 보호할 작업 수행
}
}
- transactionManager.getTransaction() 으로 트랜잭션을 시작하고, 트랜잭션 상태를 관리할 수 있는 TransactionStatus 객체를 반환받는다.
- 작업이 성공적으로 완료되면 transactionManager.commit(status) 를 호출하여 커밋하고, 예외가 발생하면 transactionManager.rollback(status) 로 롤백한다.
프로그래밍적 방식과 선언적 방식의 차이점
- 프로그래밍적 방식은 코드에서 직접 트랜잭션의 시작과 종료를 제어할 수 있어 유연하지만, 코드가 길어지고 복잡해질 수 있다.
- 선언적 방식(@Transactional 어노테이션)은 코드가 간결하고, 일반적인 트랜잭션 처리에 적합하지만, 세밀한 제어가 필요한 경우 한계가 있을 수 있다. ( https://yujuharu.tistory.com/71 )
'Java > 기본' 카테고리의 다른 글
[Java] 순환참조 (1) | 2024.11.14 |
---|---|
[Java] @NoArgsConstructor, @AllArgsConstructor (0) | 2024.11.12 |
[Java] CompletableFuture (0) | 2024.11.08 |
[Java] Future (0) | 2024.11.08 |
[Java] Java에서 final로 진짜_최종_최종_최종 불변 객체 만들기 (0) | 2024.10.31 |