TIL

250121 화 TIL

파란배개 2025. 1. 21. 17:45

@Transactional

  • 트랜잭션 단위로 메서드 실행을 관리한다.
  • 트랜잭션 내부에서 데이터를 가져올 때 **프록시(가짜 객체)**를 사용한다.
  • 주의: 트랜잭션 외부에서 호출 시 프록시 객체가 아닌 실제 객체를 반환하므로 @Transactional이 적용되지 않을 수 있다.
    • 예: work()BaseInitData 안에 정의되어 직접 호출되면, 트랜잭션 관리 범위 외부에서 실행된다. 이 경우 프록시를 거치지 않고 실제 객체를 반환하기 때문에, JPA가 제공하는 지연 로딩(Lazy Loading)이나 변경 감지(Dirty Checking) 같은 트랜잭션 기반 기능이 작동하지 않는다. 따라서 트랜잭션이 필요한 작업은 반드시 트랜잭션 관리 범위 내에서 실행해야 한다.

객체와 테이블의 연결 방식

Java

  • 두 객체는 객체 참조값(집주소나 리모컨 역할)을 통해 연결된다.

DB

  • 두 테이블은 외래키(FK)를 통해 연결된다.

외래키 규칙

  1. 1:N 관계: 외래키는 N 테이블에 저장된다.
  2. 1:1 관계: 어느 테이블에 외래키를 둘지 상관없지만, 일반적으로 포함하는 쪽에 저장한다.

@OneToMany와 관계의 주인 설정

예제

@OneToMany(mappedBy = "post")
private List<Comment> comments;
  • mappedBy: 관계의 주인을 지정하지 않은 쪽에서 설정한다.
    • 여기선 Comment가 관계의 주인이고, Post는 주인이 아니다.

관계의 주인 정의

  • 관계의 주인이 외래키 관리를 담당한다.
  • OneToMany 관계에서는 Many 쪽에서 One을 참조해야만 데이터 저장이 가능하다.

관계 설정의 중요성

  • PostComment를 저장하려면, Comment의 외래키를 통해 Post와 연결해야 한다.

관계 설정 메서드 예제

public void addComment(Comment comment) {
    comments.add(comment);
    comment.setPost(this); // 외래키 설정
}

@OneToMany 속성

속성 예제

@OneToMany(mappedBy = "post", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Comment> comments;
  • CascadeType
    • CascadeType.ALL: 부모 엔티티의 작업(저장, 병합, 삭제 등)이 자식 엔티티에 전파된다.
    • CascadeType.PERSIST: 부모 엔티티를 저장할 때 자식 엔티티도 함께 저장된다.
    • CascadeType.MERGE: 부모 엔티티와 자식 엔티티를 함께 병합한다.
    • CascadeType.REMOVE: 부모 엔티티가 삭제될 때 자식 엔티티도 함께 삭제된다.
  • orphanRemoval: 이게 참이면 관계에서 제거된 자식 엔티티는 데이터베이스에서도 삭제된다.

FetchType: LAZY vs EAGER

  • FetchType.LAZY:
    • 데이터를 실제로 사용할 때 로드된다.
    • 성능 최적화를 위해 기본적으로 Many 관계에서 사용된다.
  • FetchType.EAGER:
    • 데이터를 즉시 로드한다.
    • One 관계에서 기본적으로 사용된다.

Join Table 관리

  • 조인 테이블을 DB에서 직접 관리하기보다 JPA가 관리하도록 설정하는 것이 효율적이다.
  • 예: @JoinTable 어노테이션으로 조인 테이블을 명시적으로 정의할 수 있고 이름도 설정 가능.

정리

  • @Transactional과 프록시는 트랜잭션 범위 내에서 데이터를 관리하고 성능을 최적화하는 데 중요한 역할을 한다.
  • 객체 간의 관계와 데이터베이스 간의 관계 설정은 JPA에서 제공하는 어노테이션을 활용해 효율적으로 관리할 수 있다.
  • 관계의 주인을 올바르게 설정하고 mappedBy를 활용하면 데이터 저장과 관리를 보다 효과적으로 할 수 있다.