[JPA] 플젝 상황 적용

홍건의·2022년 4월 6일
0

JPA 학습

목록 보기
6/7

카페 프로젝트에서 데이터 구조는 아래 사진과 같다.
기존 user와 cafe 테이블만 독립적으로 있던 상황에서 review, scrap, survey가 추가됐다.

다대일 적용

(1) Entity 정의

reveiw, scrap, survey 모두 user, cafe와 다대일 단방향 관계가 적용될 수 있다.
이 케이스가 향후 확장 가능성 측면에서 가장 바람직 하다고 볼 수 있다. 예를 들어 scarp과 survey의 경우에는 향후 timestamp 등의 필드가 추가될 수 있다.

다대일 단방향이라면 Scrap Entity는 아래와 같이 정의된다.

@Entity
@Table(name="scrap")	// name 생략 가능
public class Scarp {
	
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @ManyToOne
    @JoinColumn(name = "user_id")
    private User user;
    
    @ManyToOne
    @JoinColumn(name = "cafe_id")
    private Cafe cafe;
    
}

(2) Entity Read

 String jpql = "select u from user u join .

(3) Entity Write

다대다 적용

(1) Entity 정의

이 경우 scrap과 survey만 가능하다. review는 외래키 외에 다른 필드가 존재하므로 불가능하다.

아래 케이스들은 기본키가 user_id와 cafe_id 2개 합집합이 된다.

추가로 scrap과 survey에서는

i) 단방향 관계 - user에서만 참조할 수 있도록

scrap의 경우, 테이블이 DB 상에는 존재하나 java코드의 Entity로는 존재하지 않게 된다.

@Entity
@Table
public class User {
	
    @Id
    @Column
    private String user_id;
    
    @Column
    private String nickName;
    
    @Column
    private String email;
    
    @Column
    private String age;
    
    @Column(name="profile_image_url")
    private String imgUrl;
    
    @Column
    private String gender;
    
    @ManyToMany
    @JoinTable(name = "scrap",
    		joinColumns = @JoinColumn(name="user_id"),
            iverseJoinColumns = @JoinColumn(name="cafe_id"))
    private List<Cafe> cafeList = new ArrayList<Cafe>();
    
}

###@JoinTable 속성정리###
@JoinTable.name : 연결 테이블을 지정. 예시에서는 scrap이 되는거

@JoinTable.joinColumns : 연결 테이블이랑 '정의 entity(user)'랑 매핑할 조인 칼럼을 지정. 예시에서는 scrap 테이블의 user_id가 될 것임.

@JoinTable.inverseColumns : 연결 테이블이랑 '정의 entity 기준 상대(cafe)'와 매필할 조인 칼럼을 지정. 예시에서는 scrap 테이블의 cafe_id가 되는 것임

ii) 양방향 관계 - 양쪽 객체에서 각각 상대 객체 참조 가능

@Entity
@Table
public class Cafe {

	@Id
    private String cafe_id;
    
    @ManyToMany(mappedBy = "cafeList")	// 주인은 user
    private List<User> users;
    
}

그리고 User Entity에 아래와 같이 연관관계 편의 메소드를 추가해준다.

public void addCafe(Cafe cafe) {
    	cafeList.add(cafe);
        cafe.getUsers().add(this);
}

이제 서로 서로 객체를 알아낼 수 있다.

즉시로딩과 지연로딩

우선 지연로딩은 쿼리문이 2번 나가고, 즉시로딩은 쿼리문 1번(조인)이 나간다.

프로젝트 상황에서 사실, scrap과 review라면 scrap을 조회하는 순간에 user & review가 모두 같은 시점에 필요하게 된다.
따라서 지연로딩할 필요는 없다.

@ManyToOne에서는 디폴트가 EAGER이므로 놔둔다.

지연로딩 + fetch조인의 경우에도 N+1 발생할 수 있다.

scrap Entity 조회 시 유저id랑 카페id랑 2개로 조회하면 결국 레코드 하나 뿐이다.
그리고 scrap Entity 내부에 컬렉션이 존재하지 않는다.
따라서 즉시로딩해도 N+1 문제는 발생하지 않는다.

profile
Backend Developer

0개의 댓글