728x90
반응형
✅ @Transactional을 인터페이스에 선언해도 "동작은 합니다" — 하지만 매우 제한적입니다.
📌 자세한 설명
1. Spring의 트랜잭션 처리 방식
Spring AOP(Aspect-Oriented Programming) 기반 트랜잭션 처리에서는 **프록시 객체(proxy)**가 핵심입니다.
- @Transactional은 프록시 객체가 호출을 감싸서 트랜잭션을 적용합니다.
- 이 프록시는 구현체(구현 클래스)에 적용된 애노테이션을 기준으로 동작합니다.
📌 인터페이스에 붙인 @Transactional은 기본적으로 무시되며, 구현체 클래스에 붙여야 정상 적용됩니다.
2. ✅ 왜 인터페이스에 붙여도 "동작하는 것처럼 보일 때"가 있나?
Spring Data JPA의 @Repository 인터페이스 메서드에 붙인 @Transactional은 예외입니다.
public interface UserRepository extends JpaRepository<User, Long> {
@Transactional
@Modifying
@Query("DELETE FROM User u WHERE u.status = 'INACTIVE'")
int deleteInactiveUsers();
}
- 이 경우는 Spring Data 내부에서 메서드 구현을 동적으로 생성하면서 애노테이션을 인식합니다.
- 하지만 일반적인 @Service나 사용자 정의 인터페이스는 해당되지 않습니다.
❗ 정리: 언제 어디에 붙여야 하나?
위치트랜잭션 적용 여부권장 여부
✅ 구현 클래스 (@Service, @Component) | ✔ 정상 적용 | ✔ 권장 |
❌ 일반 인터페이스 (@Service 아님) | ✖ 미적용 | ✖ 비권장 |
⚠️ Spring Data JPA 인터페이스 (@Query, @Modifying 포함) | ✔ 일부 적용됨 | ⚠ 가능 (제한적) |
반응형
✅ 올바른 구조 제안
1. 인터페이스에는 @Modifying, @Transactional 사용 X
public interface ItemRepositoryCustom {
String saveItems(List<ITEM_Dto> list);
}
2. 구현체 클래스에서 트랜잭션 선언
@Repository
@RequiredArgsConstructor
public class ItemRepositoryCustomImpl implements ItemRepositoryCustom {
private final ProcedureCallService procedureCallService;
private final Util util;
@Override
@Transactional
public String saveItems(List<ITEM_Dto> list) {
for (USP_IN_ITEM_ITEM_Dto dto : list) {
procedureCallService.call_IN_ITEM_INS(
dto.getCompanyId(),
"Item",
LocalDateTime.now(),
dto.getInType(),
dto.getAsAgentId(),
dto.getItemId(),
dto.getGoodQty(),
dto.getRecycleQty(),
dto.getBadQty(),
0,
dto.getDescription(),
util.getLoginUserId(),
"",
0
);
}
return "등록 완료";
}
}
3. 컨트롤러에서 ResponseEntity 처리
@PostMapping("/api/items/enter")
public ResponseEntity<String> saveEntering(@RequestBody List<ITEM_Dto> dtoList) {
String msg = itemRepositoryCustom.saveItems(dtoList);
return ResponseEntity.ok(msg);
}
✅ 정리
항목잘못된 사용올바른 사용
@Modifying | ❌ 인터페이스 + 일반 메서드 | ✔ JPQL/Native Query 메서드 위에만 사용 |
@Transactional | ❌ 인터페이스 선언부에 사용 | ✔ 구현 클래스에 직접 사용 |
ResponseEntity | ❌ Repository에서 반환 | ✔ Controller에서 반환 |
✅ 결론
🔹 항상 구현 클래스에 @Transactional을 붙이세요.
🔹 인터페이스에 붙이는 건 혼란을 초래할 수 있고, 동작하지 않는 경우가 많습니다.
728x90
반응형
'Java' 카테고리의 다른 글
G1 GC 영역 (Eden, Survivor, Old Gen) (0) | 2025.05.14 |
---|---|
트랜잭션이 적용되지 않고 AutoCommit 상태일 때 발생할 수 있는 문제점 (0) | 2025.05.14 |
gRPC 연동 정리 (Java vs Kotlin vs NestJS) (0) | 2025.04.02 |
Java, Kotlin, NestJS의 CI/CD 구성과 마이크로서비스 아키텍처 구성 차이 (0) | 2025.04.02 |
Java, Kotlin, NestJS에서 Kafka/DB /JWT/환경설정 (0) | 2025.04.02 |