JPA 공부

이름이름·2023년 1월 6일
0

Spring

목록 보기
11/20

Entity

엔티티란 데이터 베이스의 테이블과 연결되는 클래스를 의미한다
@Entity 를 이용해 매핑이 가능

영속성 컨텍스트

영속성 컨텍스트란 엔티티를 영구저장하는 환경이다
실제 DB에 가기전에 보관해주는 가상의DB라고 생각해면 된다

  • 임베디드 타입(복합 값 타입)
    새로운 값 타입을 직접 정의해서 사용할 수 있는데, JPA에서는 이것을 임베디드 타입(embedded type)이라 합니다.
    중요한 것은 직접 정의한 임베디드 타입도 int, String처럼 값 타입이라는 것입니다.
    '1' 대 '다' 관계에서는 무조건 '다'쪽 테이블에 외래키(FK)가 존재한다
  • 방향
    둘 중 한 쪽만 참조한다면 단방향 관계
    양쪽 모두 서로 참조하는 것은 양방향 관계
    객체를 양방향 연관관계로 만들면 연관관계의 주인을 정해야 한다.
  • 참고: 외래 키가 있는 곳을 연관관계의 주인으로 정해라.

    연관관계의 주인은 단순히 외래 키를 누가 관리하냐의 문제이지 비즈니스상 우위에 있다고 주인으로 정하면
    안된다.. 예를 들어서 자동차와 바퀴가 있으면, 일대다 관계에서 항상 다쪽에 외래 키가 있으므로 외래 키가 있는 바퀴를 연관관계의 주인으로 정하면 된다. 물론 자동차를 연관관계의 주인으로 정하는 것이 불가능 한 것은 아니지만, 자동차를 연관관계의 주인으로 정하면 자동차가 관리하지 않는 바퀴 테이블의 외래 키 값이 업데이트 되므로 관리와 유지보수가 어렵고, 추가적으로 별도의 업데이트 쿼리가 발생하는 성능 문제도 있다.

  • 실무에서는 가급적 Getter는 열어두고, Setter는 꼭 필요한 경우에만 사용하는 것을 추천

    실무에서 엔티티의 데이터는 조회할 일이 너무 많으므로, Getter의 경우 모두 열어두는 것이 편리하다. Getter는 아무리 호출해도 호출 하는 것 만으로 어떤 일이 발생하지는 않는다. 하지만 Setter는 문제가 다르다. Setter를 호출하면 데이터가 변한다. Setter를 막 열어두면 가까운 미래에 엔티티에가 도대체 왜 변경되는지 추적하기 점점 힘들어진다. 그래서 엔티티를 변경할 때는 Setter 대신에 변경 지점이 명확하도록 변경을 위한 비즈니스 메서드를 별도로 제공해야 한다.

           

변경 지점이 명확하도록 변경을 위한 비즈니스 메서드를 별도로 제공해야 한다.

  • @Column은 객체 필드를 테이블의 컬럼에 매핑시켜주는 어노테이션입니다.

  • 실무에서는 @ManyToMany 를 사용하지 말자

    @ManyToMany 는 편리한 것 같지만, 중간 테이블( CATEGORY_ITEM )에 컬럼을 추가할 수 없고, 세밀하게 쿼리를 실행하기 어렵기 때문에 실무에서 사용하기에는 한계가 있다. 중간 엔티티( CategoryItem 를 만들고 @ManyToOne , @OneToMany 로 매핑해서 사용하자. 정리하면 대다대 매핑을 일대다, 다대일 매핑으로 풀어내서 사용하자.

모든 연관관계에는 지연로딩으로 설정해야함
즉시로딩을 사용하게되면 뭐 하나 조회할 때 그 테이블이랑 연관되어있는 테이블들까지 동시에 즉시 건드리기 때문에 좋지않음

@XToOne(OneToOne, ManyToOne)같이 "하나를 찌르는 느낌"의 경우는 기본이 fetch전략이 EAGER로 되어있음 (fetch = FetchType.EAGER)
따라서 하나하나 찾아서 LAZY로 바꿔줘야함
command+shift+F (검색)

변경감지와 병합

데이터 변경할 때 lombok으로 만들어 놓은 setter를 통해 setFunc(인자)하면 알아서 JPA 쿼리 날려줘서 commit까지 알아서 해주는 듯
준영속 엔티티라고 영속성 컨텍스트가 더이상 관리하지 않는 엔티티를 말하는데 이미 한번 DB에 갔다왔거나 new로 임의로 만들어도 ID와 같은 식별자가 존재한다면 준영속 엔티티라고 볼 수 있다
이런 준영속 엔티티를 수정하는 방법에는 변경감지와 병합(merge) 2가지가 있는데 일단 결론만 말하면 변경감지의 방법을 써야한다

@Transactional
void update(Item itemParam) { //itemParam: 파리미터로 넘어온 준영속 상태의 엔티티
Item findItem = em.find(Item.class, itemParam.getId()); //같은 엔티티를 조회한다.
findItem.setPrice(itemParam.getPrice()); //데이터를 수정한다. }

변경감지의 방법은 위와 같이 그냥 조회해서 setter로 원하는 값만 수정하는 방식을 이야기함

profile
공부 정리

0개의 댓글