Dev

[jpa] 참조키를 이용한 1:1 단방향 연관

Ryan Woo 2019. 3. 2. 22:05

jpa 책을 두번이나 읽었는데 1년 지나니 거의 백지 상태라 기록차 포스팅 시전

1. [jpa] 1:1 단방향 연결

1
2
3
4
5
6
7
8
9
public class Member {
    @Id
    private String email;
    private String name;
 
    @Temporal(TemporalType.DATE)
    private Date createdDate;
}
 
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class MembershipCard {
 
    @Id
    @Column(name = "card_number")
    private String number;
 
    @OneToOne
    @JoinColumn(name = "member_email")
    private Member owner;
 
    @Temporal(TemporalType.DATE)
    @Column(name = "expiry_date")
    private Date expiryDate;
 
    protected boolean enabled;
}
cs


위와 같이 테이블이 생성 된다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
    @Test
    public void 참조키를이용한일대일단방향연관() {
 
        // 1. 멤버 생성 및 가져오기
        Member user = Member.builder()
                .email("ryan@naver.com")
                .name("Ryan")
                .createdDate(new Date())
                .build();
        memberRepository.save(user);
 
        ZonedDateTime zonedDateTime = ZonedDateTime.of(2020,12,3123,59,59,0, ZoneId.systemDefault());
        Date expiryDate = Date.from(zonedDateTime.toInstant());
        Optional<Member> owner = memberRepository.findById("ryan@naver.com");
 
        // 2-1. 멤버쉽 카드 생성
        MembershipCard membershipCard = MembershipCard.builder()
                .number("1234")
                .owner(owner.get())
                .expiryDate(expiryDate)
                .build();
        membershipCardRepository.save(membershipCard);
        // member_email 필드에 앞서 만든 member 의 email 이 저장됨
 
        // 2-2. 멤버쉽 카드를 생성하되, 연관 관계를 설정하지 않음
//        MembershipCard membershipCard = MembershipCard.builder()
//                .number("1234")
//                .expiryDate(expiryDate)
//                .build();
        membershipCardRepository.save(membershipCard);
        // member_email 필드에 null 이 저장됨
        
        // 3. 멤버쉽 카드를 조회하면, Member 와 아우터 조인이 걸려 함께 조회됨
        Optional<MembershipCard> find = membershipCardRepository.findById("1234");
        // 2-1, 2-2 모두 기본적으로 아우터 조인이 걸림
        
        // 4-1. 멤버쉽 카드에 할당된 멤버를 지우려고 하면?
//        memberRepository.deleteAll();
        // 익셉션이 발생한다. 멤버의 email 이 참조 관계가 생겼기 때문...
 
        // 4-2. 멤버쉽 카드를 지우려고 하면?
        membershipCardRepository.deleteAll();
        // 정상적으로 삭제가 됨
 
        // 5. 관계가 없어진 후 멤버를 삭제
        memberRepository.deleteAll();
        // 참조 관계의 레코드가 삭제 되었기 때문에 정상 삭제
 
        assertThat(membershipCardRepository.findById("1234")).isEmpty();
        assertThat(memberRepository.findById("ryan@naver.com")).isEmpty();
    }
cs

주의 : 연관 데이터가 있는 상태에서 연관 주체(여기서는 MembershipCard)가 아닌 레코드 삭제시 Exception 이 발생