본문 바로가기
코딩 정리/Spring

[항해] Spring 숙련주차 #1

by 실버십 2023. 4. 18.

 

<JPA> 심화

 이번 주 목표 

 1. 내부 동작에 대한 이해를 기를 수 있는 "영속성 컨텍스트"에 대해서 이해하기 

 2. 입문주차 내용을 복습 및 심화시켜 구체적으로 다양한 어노테이션 배워 다양한 상황에 대응할 수 있 있는 능력 기르기 

 3. 나중에 JPA 만으로 처리가 어려운 상황을 대응하기 위한 내용 배우기 

 

 

스레드 : 프로그램 내부에서 일을 하는 일꾼

하나의 큰 일을 동시에 처리하면 동시성 문제가 생길 수 있다. 그것을 방지하기 위해 특정 리소스나 정보는 공유하지 못하게 하는 등의 처리 필요하다. 여러 스레드가 하나의 엔티티 매니저를 이용할 수 없도록 처리해야 한다. 

그래서 엔티티 매니저 팩토리에서 필요할 때마다 여러개의 엔티티 매니저를 생성해야 한다. 

 

영속성 컨텍스트란?

엔티티를 영구 저장하는 환경 

어플리케이션이 데이터베이스에서 꺼내온 데이터를 보관하는 역할을 하는데, 영속성 컨텍스트는 엔티티 매니저를 통해 엔티티를 조회하거나 저장할 때 엔티티를 보관하고 관리한다. 

 

JPA엔티티 상태

더보기
* 비영속(new) : 영속성 컨텍스트와 관계가 없는 새로운 상태 
해당 객체의 데이터가 변경 되든 말든 실제 DB 속 데이터와 관련 없이 Java 객체인 상태 
 예
 Member min = new Member();
 member.setId("min");

* 영속(Managed) : 엔티티 매니저를 통해 엔티티가 영속성 컨텍스트에 저장되어 관리 되는 상태 
데이터의 생성, 변경 등을 JPA가 추적하면서 필요하면 DB에 반영
 예
 em.persist(min);
 
* 준영속(Detached) : 영속성 건텍스트에서 관리 되다가 분리된 상태 
 예
 em.detach(min);  // 엔티티를 영속성 컨텍스트에서 분리
 em.clear();  // 영속성 컨텍스트 비우기
 em.close();  // 영속성 컨텍스트 종료 
 
* 삭제(Remove) : 영속성 컨텍스트에서 삭제된 상태 
 예
 em.remove(min);

음 전혀 모르겠다. 

 

 

엔티티 매핑 심화 

 - 엔티티 관련 어노테이션 

 

@Entity 

 기본 생성자 필수! (파라미터가 있는 생성자가 있다면 자바가 알아서 만들어주지 않으므로) 

 final 클래스 enum, interface 등에서 사용 부락 

 저장할 필드라면 final 절대 사용하지 말것!

 

@Table

 엔티티와 매핑할 테이블의 이름 

 생략하는 경우 어떻게 될까?

 

@Column 

 객체 필드를 테이블 컬럼에 매핑하는데 사용

 생략 가능 

 속성들은 자주 쓸 일이 없고, 특정 속성은 effect가 있다. 주의할것 

 

@Enumerated

 Java Enum을 테이블에서 사용

 Ordinal, String 속성이 있는데, 일반적으로 String을 사용

(왜냐, String인 경우 해당 문자열 그대로 저장해서 비용은 많이 들지만 나중에 Enum 이 변경되어도 위험할 일이 없기 때문에)

 

 

연관관계

단방향 연관관계

 @ManyToOne

 다대일(N:1) 관계 - 한명의 유저가 여러개의 주문 

 주요 속성 : optional, fetch, cascade

   - optional 을 false 로 설정하면 항상 연관된 엔티티가 있어야 생성할 수 있다는 의미 

  

 @JoinColumn(name="food_id")

 외래 키 매핑시 사용 

 

 

양방향 연관관계  ??? 

 @ManyToOne : 단방향과 같다 

 

 @OneToMany 

 

 연관관계의 주인만이 데이터베이스의 연관관계와 매핑되고, 외래키를 관리 가능하다.

 연관관계 주인 = 외래 키 관리자

 연관관계의 주인에 의해 mappedBy 된다

 

양방향 연관관계 주의점

 연관관계의 주인에는 값을 입력하지 않고, 주인이 아닌 곳에만 값 입력 -> 외래 키 값에 null 저장 

  -> 해결법 : 순수한 객체까지 고려한 양방향 연관관계 : 양쪽 방향 모두에 값을 넣는것 

  -> 해결법 : 연관관계 편의 메소드 

private Oder order;
  public void setMember (Member member) {
  this.member = member;
  member.getOrders().add(this);  // this => 엔티티의미
  }

 

 

프록시

 JPA는 굳이 필요없는 DB 조회를 줄이면서 성능을 최적화한다. 

 이 문제를 해결하기 위해 엔티티가 실제 사용될 때ㅏ지 데이터베이스 조회를 지연하는 방법 제공 = 지연 로딩 

 지연 로딩 기능을 사용하려면 실제 엔티티 객체 대상에 데이터베이스 조회를 지연할 수 있는 가짜 객체 = 프록시 객체 

 

즉시로딩 : 엔티티 조회시 여관된 엔티티 함께 조회, 연관된 엔티티를 조인해서 다 글어와 버린다

  : @ManyToOne(fetch = FetchType.EAGER)

지연로딩 :  연관된 엔티티 실제 사용 시 조회, 실제로 가짜 객체를 이용하면 별도의 쿼리가 나간다 

  : @ManyToOne(getch = FetchType.LAZY)

=> 정확하게 이해하고 꼭 필요한 상황이 아니라면 지연로딩으로 할 것! 

 

기본값은 아래와 같지만 웬만해서는 LAZY 쓰도록!

 @ManyToOne, @OnToOne : 즉시로딩 (FetchType.EAGER)

 @OneToMany, @ManyToMany : 지연로딩(FetchType.LAZY)

 

 

영속성 전이

특정 엔티티를 영속 상태로 만들 때 연관된 엔티티도 함께 영속 상태로 만들고 싶으면 영속성 전이 사용 

JPA 는 cascade 옵션으로 영속성 전이를 제공 

 => 영속성으로 묶어서 같이 관리하고 싶을때

다양한 옵션이 있지만 나중에 회원탈퇴 등의 로직구현시 다시 공부하세요! :)

@OneToMany (mappedBy = "person", cascade = CascadeType.ALL)
private List<Address> address;