원자성(Atomicity)
일관성(Consistency)
격리성(Isolation)
지속성(Durability)
BEGIN TRANSACTION;
insert into MEMBER VALUES
(1, now(), now(), 'hgd1@gmail.com', 'MEMBER_ACTIVE', '홍길동1', '010-1111-1111');
COMMIT;
BEGIN TRANSACTION;
insert into MEMBER VALUES
(2, now(), now(), 'hgd2@gmail.com', 'MEMBER_ACTIVE', '홍길동2', '010-2222-2222');
H2 웹 콘솔에 입력 시 commit을 하지 않은 아래 정보는 저장되지 않음
Auto commit 기능을 끄고 확인 / 새로 고침을 해줘야 정상적으로 결과가 보인다.
JPA API를 사용한 commit 과정에서 JPA 기술을 사용한 데이터베이스와의 인터랙션은 내부적으로는 JDBC API를 통해서 이루어짐
BEGIN TRANSACTION;
insert into MEMBER VALUES
(1, now(), now(), 'hgd1@gmail.com', 'MEMBER_ACTIVE', '홍길동1', '010-1111-1111');
ROLLBACK;
COMMIT;
logging: # 로그 레벨 설정
level:
org:
springframework:
orm:
jpa: DEBUG
import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional
public class MemberService {
...
}
해당 클래스의 모든 메서드에 트랜잭션 적용
커밋 출력 로그
// 트랜잭션 생성
: Creating new transaction with name [com.codestates.member.service.MemberService.createMember]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
// 커밋
: Initiating transaction commit
: Committing JPA transaction on EntityManager [SessionImpl(501161200<open>)]
// 트랜잭션 종료
: Not closing pre-bound JPA EntityManager after transaction
// EntityManager 종료
: Closing JPA EntityManager in OpenEntityManagerInViewInterceptor
: Initiating transaction rollback
: Rolling back JPA transaction on EntityManager [SessionImpl(1632113004<open>)]
: Not closing pre-bound JPA EntityManager after transaction
: Closing JPA EntityManager in OpenEntityManagerInViewInterceptor
import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional
public class MemberService {
...
@Transactional(readOnly = true) // (1)
public Member findMember(long memberId) {
return findVerifiedMember(memberId);
}
...
}
PROPAGATION_REQUIRED,ISOLATION_DEFAULT, readOnly
@Transactional
@Service
public class OrderService {
...
public Order createOrder(Order order) {
verifyOrder(order);
Order savedOrder = saveOrder(order);
updateStamp(savedOrder); // MemberService 메서드 호출
throw new RuntimeException("rollback test");
// return savedOrder;
}
...
}
@Transactional
@Service
public class MemberService {
...
// (1)
@Transactional(propagation = Propagation.REQUIRED)
public Member updateMember(Member member) {
Member findMember = findVerifiedMember(member.getMemberId());
Optional.ofNullable(member.getName())
.ifPresent(name -> findMember.setName(name));
Optional.ofNullable(member.getPhone())
.ifPresent(phone -> findMember.setPhone(phone));
Optional.ofNullable(member.getMemberStatus())
.ifPresent(memberStatus -> findMember.setMemberStatus(memberStatus));
return memberRepository.save(findMember);
}
트랜잭션의 경계에서 진행 중인 트랜잭션이 존재할 때 또는 존재하지 않을 때, 어떻게 동작할 것인지 결정하는 방식
Propagation.REQUIRED
Propagation.REQUIRES_NEW
Propagation.MANDATORY
Propagation.NOT_SUPPORTED
Propagation.NEVER
다른 트랜잭션에 영향을 주지 않고 독립적으로 실행되어야 하는 격리성을 @Transactional 애너테이션의 isolation 애트리뷰트를 통해 조정 가능
트랜잭션의 격리 레벨은 일반적으로 데이터베이스나 데이터소스에 설정된 격리 레벨을 따르는 것이 권장
Isolation.DEFAULT
Isolation.READ_UNCOMMITTED
Isolation.READ_COMMITTED
Isolation.REPEATABLE_READ
Isolation.SERIALIZABLE