[jpa] transaction propagation
2024.05.23 - [개발/spring] - [transaction] isolation level
[jpa] transaction isolation level
2024.05.22 - [개발/sql] - DB isolation level DB isolation levelisolation level 이란 무엇인가?디비 동시성을 관리하고 데이터 정합성을 유지하기 위해 서로 다른 트랜젝션끼리의 관계를 정의한 것 존재 이유?언
bangpurin.tistory.com
A transaction is a group of sequential operations on a database that forms a logical unit of working with data.
Transactions are used to maintain the consistency and integrity of data in a database.
It’s important to know that transactions are thread-local, so they apply to the current thread only.
propagation: 세션의 트랜젝션을 어떻게 이용할지; 무결성과 정합성을 유지하기 위한 방법
종류 | 트랜젝션 존재 시 | 트랜젝션 미존재 시 | 비고 |
REQUIRED | 기존 트랜잭션 이용 | 신규 트랜잭션 생성 | 기본값 |
SUPPORTS | 기존 트랜잭션 이용 | 트랜잭션 없이 수행 | |
MANDATORY | 기존 트랜잭션 이용 | exception 발생 | 꼭 이전 트랜잭션이 있어야 하는 경우 |
NEVER | exception 발생 | 정상적으로 트랜잭션 없이 수행 | 트랜잭션 없을 때만 작업이 진행되어야할 때 |
NOT_SUPPORTED | 기존 트랜젝션은 중지하고 대기, 트랜젝션 없이 실행하다가 끝나면 기존 트랜젝션 실행 | 트랜잭션 없이 로직 수행 | 기존 트랜잭션에 영향을 주지 않아야할 때 |
REQUIRES_NEW | 현재 트랜잭션은 중지되고 대기. 새로운 트랜잭션을 생성하고 종료되면 현재 트랜젝션이 다시 진행 | 신규 트랜잭션을 생성하고 로직을 실행 | 이전 트랜잭션과 구분하여 새로운 트랜잭션으로 처리가 필요할 때; 락과 함께 사용할 경우 데드락 조심 |
NESTED | 현재 트랜잭션에 Save Point를 걸고 이후 트랜잭션을 수행 | REQUIRED와 동일하게 작동 (신규 트랜잭션을 생성하고 로직이 수행) |
DBMS특성에 따라 지원 혹은 미지원; jpa에서 사용 불가 |
- Nested is not possible in the JPA dialect because you cannot create a save point here. Nested, unlike Required New, creates a kind of save point. For example, if you are updating a huge batch of data, you won’t have to roll back everything in case of an error; you may roll back just to the save point.
두 함수간 트랜젝션을 전파하는 경우(출처: chat gpt..)
부모 함수 -> 자식 함수라고 가정할 때
트랜잭션 전파의 핵심은 부모 메서드에서 트랜잭션이 이미 시작되었는지 여부입니다. parentMethod()에서 트랜잭션이 시작되었다면, 그 안에서 호출되는 모든 자식 메서드(접근 제어자 public이든 private이든 상관없이)는 동일한 트랜잭션 경계 내에서 실행됩니다.
부모 | 자식 | 부모 transaction 전파 여부 |
public + @Transactional | private in same class | O |
public + @Transactional | public in same class, @Transactional유무 상관없이 | O |
public + @Transactional | public in different class, @Transactional유무 상관없이 | O |
1. Transaction은 public에서 시작, private은 함수의 일부라 판단하여 트랜젝션 이어짐
@Service
public class MyService {
@Transactional
public void parentMethod() {
// Transaction starts here
privateChildMethod(); // This method is part of the same transaction
}
private void privateChildMethod() {
// This method participates in the transaction started by parentMethod
}
}
2. 자식 함수가 같은 클래스에 있으면 부모 트랜젝션 전파됨
만약 반대로 부모가 @TRANSACTIONAL이 없고 같은 클래스의 자식에게 @TRANSACTIONAL이 있다면 자식의 트랜젝션은 신규로 생성되지 않음(프록시를 타지 않아서)
@Service
public class MyService {
@Transactional
public void parentMethod() {
// Transaction starts here
publicChildMethod(); // This call bypasses the proxy
}
public void publicChildMethod() {
// This method does not participate in the transaction started by parentMethod
}
}
3. 부모와 자식 클래스가 다를 경우, 자식이 기본 Transaction을 사용할 경우
클래스가 다를 경우 자식 함수가 proxy의 영향을 받기 때문에 부모의 트랜젝션이 자식에게 전파된다.
자식 함수가 @Transaction 어노테이션이 있건 없건 전파되는데, 만약 자식 함수도 Transaction 어노테이션이 있고 별다른 propagation 설정이 없다면 기본 전파 옵션이 Propagation.REQUIRED 이기 때문에 기존 트랜젝션을 탄다. 이 경우가 transaction 중첩이 가능한 부분이고, 위 옵션에 따라 달라진다.
@Service
public class ParentService {
@Autowired
private ChildService childService;
@Transactional
public void parentMethod() {
// Transaction starts here
childService.childMethod(); // This call goes through the proxy
}
}
@Service
public class ChildService {
@Transactional //있건없건 트랜젝션 영향 받음
public void childMethod() {
// This method participates in the transaction started by parentMethod
// because the call goes through the Spring proxy
}
}
https://www.baeldung.com/spring-transactional-propagation-isolation
한 번쯤 읽어볼 만한 시행착오
https://technixc.medium.com/how-to-use-transactional-annotation-like-a-pro-4129308ad069