당니의 개발자 스토리
양방향 연관관계와 연관관계의 주인 2 - 주의점, 정리 본문
양방향 연관관계와 연관관계의 주인 2 - 주의점, 정리
이제 양방향 맵핑 시에 가장 많이 하는 실수.

연관관계 주인의 값을 입력하지 않음. 이걸 예시로 보여드릴게요.
자 이거는 정말 많이 실수하시는 부분이고 커뮤니티에도 질문이 한 번씩 올라와요.

자 여기 보시면 정말 단순하게 Team 하나 만들고 Member 하나 만들었단 말이에요.

Member와 Team의 순서를 좀 바꿔 볼게요.

그리고 제가 team.getMembers().add(member) 해서 집어넣었어요. 분명히 지금 연관관계로는 집어넣은게 맞죠?

Member에는 아무것도 손 댄게 없어요. 이제 어떻게 되는지 실행을 해보면,

Insert 쿼리는 분명히 두 방이 나갔어요. 그럼 db에 가보시면,

지금 Member 테이블을 보면 memberId, username이 있는데 teamId가 null이죠. 이게 왜 그럴까요?

연관관계 주인이 지금 잘 보면 Member에 있는 이 team이 연관관계 주인이란 말이에요.

Team에 있는 members. 이거는 mappedBy에서 읽기 전용이에요. JPA에서 업데이트 할 때나 Insert, 즉 변경할 때는 members를 아예 안 봐요. 이거는 그냥 읽기 전용인 거예요. 그러니까 가짜 맵핑인 거죠.
그래서 member.setTeam(team)을 하셔야 하는데 그러면 다시 순서를 바꿔야겠죠. team을 먼저 저장해야하니까.

이번에는 연관관계의 주인에만 값을 넣어보고 연관관계의 주인이 아닌 건 주석처리 할 게요. 이렇게 하면 정상적으로 값이 들어갑니다. 지금 이 부분이 중요한 겁니다. 뭐 쿼리는 잘 나갔을 거고요.

지금 보시면은 Member의 TEAM_ID가 1번으로 제대로 들어가 있죠. '어 그러면 둘다 넣어도 되지 않나요?' 궁금하실 수가 있죠. 답은 가능합니다 입니다.

주석처리 했던 걸 다시 넣어볼게요. 어차피 얘는 읽기 전용이기 때문에 JPA에서 update 할 때 이 값을 안 써요. 실행해보면,

쿼리를 날려보면 이 값이 제대로 나왔죠.

그래서 양방향 맵핑 시에 연관관계가 주인이 아닌, 역방향에만 값을 넣어가지고 외래 키 값이 null인 거. 이거를 제일 조심하셔야 됩니다. 분명히 이렇게 말씀드려도 운영에서 꼭 한번씩 실수를 합니다.
그러면 이제 그런 의문이 들어요. '그럼 어떻게 해야 되죠? 연관관계 주인에만 값을 세팅하면 되는 건 알겠는데..' 가급적이면 양방향 맵핑할 때는 사실 답이 있습니다.
뭐냐면 양쪽에 다 값을 넣어주는 게 맞아요. 그런데 사실은 JPA 입장에서 보면

이게 맞는 코드긴 해요. Team 만들고 Member에다가 세팅해주고 persist 하면,

이게 연관관계의 주인이니까 외래 키를 꺼내서 넣겠죠. 어차피 team.getMembers는 안 보니까.
그런데 이게 진짜 객체지향적으로 생각을 해보시면 양쪽에다 값을 걸어야 돼요.

지금 Team을 찾아서 findTeam.getMember() 하면 어떻게 되는지 iterator를 돌려가지고 제가 뽑아볼게요.

이렇게 하면 위를 보시면 제가 List에다가 세팅한 게 없죠. 그런데 지금 flush, clear 깨끗하게 해주고, 깔끔하게 DB에서 Team 데이터를 새로 가지고와서 iterator를 돌리면, 제가 List에 세팅한 게 없어도 getMembers 해서 돌리면 당연히 반영이 되어있는 걸 확인하실 수 있겠죠.

여기 member1이라고 잘 나옵니다. JPA에서 이걸 지연 로딩이라고 표현을 하는데

이 Team에서 getMembers 라고 호출을 하죠.

그리고 여기 보시면 members 가져와서 iterator를 돌리죠.

이때 잘 보시면 JPA가 무슨 일을 하냐면, 이 쿼리. 이 Team Select 쿼리가 나가죠. 이거는 이제 Team을 조회했을 때

이 라인에서 호출이 된 거고,

이 Select에서 보시면 Member를 또 Select 쿼리가 한방 나갑니다. 그건 이 부분에서 나가는 건데요. 실제 Member의 데이터를 로딩 했을 때 JPA에서 어떻게 하냐면

이렇게 members의 데이터를 끌고 오는 시점에서 실제 사용하는 시점에 쿼리를 한방 날립니다.

그래서 지금 보면은 Foreign Key 값 다 세팅 되어있고 하니까

여기 쿼리가 나갈 때 Foreign Key 값으로 쿼리를 날려서 나랑 연관된 Member를 가지고 옵니다. 이렇게 되어있기 때문에 사실 값을 굳이 세팅을 안해줘도,

그러니까 컬렉션에 이렇게 add 해서 Member를 안 넣어줘도

이 값을 조회하면 JPA를 통해서 값이 출력이 돼요. 그런데 뭔가 이상하잖아요.

이걸 안 넣어주면 뭔가 좀 객체지향스럽지 않잖아요. 이걸 안 넣어주면 사실 두 군데서 문제가 돼요.

첫 번째 무슨 문제가 있냐면, 이걸 완전히 flush, clear 해버리면 문제가 없어요.

그런데 제가 flush, clear를 주석처리 했어요.

그러면 제가 이걸 jpa에서 em.find 해서 Member를 가지고 와요. 그러면 이거는 잘 생각해 보세요.

얘는 지금 1차 캐시에 있단 말이에요. 영속성 컨텍스트에 들어있는 거예요. 언제?

여기서 집어넣은 상태 그대로 들어가 있는 거예요. 여기 집어 넣을 때 보면 지금 값 세팅하고 연관관계 다 들어가 있죠.

이게 다 물려서 그냥 메모리에 올라가 있어요.

그러니까 flush, clear를 안 하면 지금 1차 캐시에서 조회된 게 그대로 튀어나오는 거에요. 그거를 갖다가 보시면

여기 getMembers 컬렉션에 값이 있을까요, 없을까요? 없단 말이에요.

왜냐하면 findTeam이 지금 영속성 컨텍스트에 넣을 때 보시면 이 team 상태 그대로 들어가 있는 거에요.
그래서 이렇게 실행해 보면 지금 DB에 Select 쿼리가 안 나갈 거에요.

자 보시면 Insert 쿼리만 나가죠. Insert 쿼리는 트랜잭션이 커밋할 때 나간거고,

여기 잘 보시면 이 member1은

이 루프를 돌려서 나가는 이 부분이죠. 여기를 지금 잘 보시면

이걸 주석처리 해서 돌려보면,

지금 아무것도 안나와요.

알아보기 쉽게 선을 그어서 돌려 보면, 아무것도 없죠. 여기서 size() 찍으면 0으로 나와요. 왜냐하면,

지금 이 Team에 add(member)도 없단 말이에요. 그냥 Team이 그대로 엔티티 영속성 컨텍스트에 들어가 있는 거예요. 그러면 Team 컬렉션을 까보면 아무것도 없단 말이에요.

메모리에서도 아무것도 없이 또 그대로 가져온 상태예요. 지금 순수한 객체 상태라고 보시면 되거든요. 그걸 그대로 가져온 거니까 당연히 컬렉션에도 값이 없겠죠.

그래서 이미 1차 캐시는 로딩이 되어있고,

여기 보시면 출력되는 게 없는 거에요. 그래서 이런 것도 겪을 수 있을 수가 있고,

또 하나가 어쨌든 이런 케이스 때문에 이거를 객체 지향적으로 생각을 해봐도 양쪽으로 다 값을 세팅해주는 게 맞아요. Team에도 값을 세팅해주고 Member에도 값을 세팅해주고 양쪽에 다 넣어주시는 게 맞아요.
그리고 또 하나가 테스트 케이스 작성하는 거죠. 나중에 테스트 케이스를 작성하실 때는 jpa 없이도 순수하게 자바 코드 상태로 테스트 케이스를 작성하거든요. 그 케이스에도 member.getTeam 이면 되는데 반대로 하면 null이고 empty가 나오고 이상하게 나오는 거에요. 이게 안 맞는 거죠.

그래서 결론은 뭐냐면 양방향 연관관계를 세팅하실 때는 양쪽에다가 값을 다 세팅을 해주는 게 맞습니다. 양쪽에다 값을 세팅을 하셔야 돼요.

그래서 이제 순수 객체 상태를 고려해서 항상 양쪽에 값을 설정 하셔야 됩니다.

JPA에서 완전히 clear를 해버리면 1차 캐시에 아무것도 없단 말이에요. 그럼 db에서 다시 조회해와요. 이 경우에는 DB에서 다시 조회해왔기 때문에 JPA가 Foreign Key가 있다는 것도 알고 해서 members도 다시 db에서 조회해야 되겠다는 메커니즘이 JPA가 내부적으로 동작을 해요.

그런데 순수하게 1차 캐시에 이거를 넣은 상태에서는

이 값이 없으면 JPA가 못 읽어드립니다. 최악의 경우에 버그가 발생할 수 있겠죠.

그래서 결론적으로 말씀드리면 순수 객체 상태를 고려해서 양쪽에 항상 값을 세팅 하셔야 됩니다.
자 그럼 이제 제가 추천하는거 뭐냐면, 이렇게 되어버리면 이제 문제가 뭐냐?

이 ** 포인트랑 이 포인트. 둘 다 넣어야 되잖아요. 근데 사람이기 때문에 로직이 이렇게 되어있으면 둘 다 넣어야 되는 걸 깜빡깜빡 한단 말이에요.
그래서 제가 추천하는 방법은 뭐냐면 저는 이걸 연관관계 편의 메서드라고 하는데, 이거를 만드시는 걸 권장드려요.

예를 들면 Member의 setTeam을 하실 때 이렇게 넣는 거죠.

이렇게 하시면 되는데, 이 this가 현재 내 자신입니다.

나 자신 인스턴스를 넣어주고

여기서 이 team.getMembers().add(member) 코드를 그냥 지우는 겁니다. 그러면은 이제 실수하지 않겠죠.

왜냐하면은 이 Member의 Team을 세팅하는 시점에 Team에도 이거를 세팅해 줄 수 있습니다. 이렇게 돌려보시면
그럼 이제 양쪽으로 다 세팅이 딱 들어간 거거든요. 이렇게 하시면 이제 어쨌든 이 메서드를 약간 원자적으로 쓸 수 있는 거죠. 하나만 호출해도 양쪽으로 값이 딱 걸리는 거죠. 저는 이걸 연관관계 편의 메서드라고 부르고요. 그리고 약간 이건 개인적인 취향인데 저 같은 경우에는 연관관계 편의 메서드나 뭔가 JPA의 상태를 변경하는 것은 set을 잘 안 써요. 이 set은 자바의 getter, setter 관례 때문에 단순하게 로직이 없이 set set 할 때만 넣고요. 로직이 들어가면

저는 이렇게 합니다. changeTeam 이런식으로 이름을 바꿔둡니다.

그러면 이게 단순한 getter setter 관례에 의한 게 아니니까, 뭔가 '아 지금 되게 중요하게 뭔가 하는 거구나' 라는 걸 알 수가 있죠.

이렇게 돌리시는 것을 권장 드립니다. 사실 연관관계 편의 메서드를 좀 더 깊이있게 쓰려면 더 복잡해요.

이게 Team 안에 Member에 진짜 내가 있냐, 없냐 등등 null 체크도 해야 되고 사실 체크할 게 많거든요. 나를 바꾸면 Member 입장에서는 반대로 기존에 있던 것을 빼고 나를 다시 넣어야 되잖아요. 뭐냐면 Team이 바뀌면 기존에 있는 것에서 또 막 여기서 빼내고 해야 되거든요. 비즈니스 로직이 정말 복잡하시면 그것까지 넣으시면 되고요.

아니면 이렇게 이제 간단하게 연관관계 편의 메서드를 쓰시면 됩니다. 너무 깊은 내용이어서 그렇게까지 복잡한 것은 궁금하신 분들은 JPA 책을 참조하시면 되구요. 보통 실무에서 여기까지만 해도 크게 무리는 없습니다.

그리고 또 하나가 예를 들어서 이렇게 넣으실 때도 있는데,

반대로 이런 식으로 코드를 짜기도 해요. 저 같은 경우에는 짤 때 둘 중에 하나를 정하거든요. Member를 기준으로 Team을 넣을까, 아니면 Team을 기준으로 Member를 집어 넣을까 정하는 편인데 그러면 여기에다가 Member를 딱 집어 넣고 만들어 볼게요.

setter를 다시 만들어준 다음에, addMember 메서드를 만들어서 이런 식으로 짜주면 됩니다. 대신에 이때 조심해야 될 것은 이렇게 연관관계 편의 메서드가 양쪽에 다 있으면 좀 문제를 일으킬 수도 있거든요. 그래서 한쪽 거는 지워주시면 됩니다.

이렇게 하면 이제 Team에다가 addMember 해가지고 Member를 집어 넣으면 되죠. 그니까 둘중에 하나를 정하시면 돼요. 아까 말씀드렸던 연관관계의 주인 같은 경우에는

Member에 있는 이게 연관관계의 주인인거고, 값을 세팅하는건 내 마음이잖아요. 이거를 뭐 어떤 메서드를 통해서 할지는 내가 잘 넣어서

addMember 이런 식으로 푸셔도 되구요. 아까처럼 뭐 반대쪽에서 하셔도 되구요.

Member에다가 Team을 세팅해 주면서 나야 라고 하면서 이 members 컬렉션을 넣어주셔도 되고. 뭐 이걸 이쪽에서 하든 저쪽에서 하든 중요한 거는 둘 중에 한 곳에서만 하시는 게 맞아요. 이거를 두 개 다 하면 잘못하면 최악의 경우에 무한 루프 걸릴 수도 있고 고민거리들이 많아지거든요. 그렇게 해서 넣으시면 됩니다.
연관관계 편의 메서드는 1 쪽에 넣어도 되고 다 쪽에 넣으셔도 돼요. 근데 실제 애플리케이션 개발 하시다 보면 어디가 맞는지 상황마다 조금씩 달라요. 그 상황을 보시고 하시면 됩니다.

그리고 이제 조심해야 될게 양방향 맵핑 시에 무한 루프를 조심해야 됩니다. 뭐가 문제가 되냐면 lombok이나 JSON 생성 라이브러리에서 문제가 됩니다. 왜 문제가 되냐?

자 보세요. Member에서 toString을 생성해볼게요. 이게 라이브러리 같은 걸로 생성하면

이런 식으로 생성이 된단 말이에요. 지금 잘 보시면 toString이 id, username, team을 불러왔어요.

이 team은 team.toString을 또 호출한다는 의미거든요. 그러면 Team에 가보면,

여기 Team에서도 toString을 생성하잖아요. 잘 보시면 id, name, members가 들어와요. 이 members는 컬렉션 하나하나 안에 있는 member의 toString을 다 호출해요. 그러면 지금 양쪽으로 toString을 무한 호출하게 됩니다. lombok 같은 라이브러리에서 toString을 만들면 방금처럼 다 만들어버리는 거거든요.

이렇게 sout 해서 findTeam을 찍으면 그냥 toString을 찍는 거랑 똑같으니까 저게 다 나가겠죠.

돌려보면, StackOverFlow가 나가는 걸 보실 수 있죠. 왜냐하면 양쪽으로 계속 호출하기 때문이에요. 그러면서 그냥 뻗어 버리는 거죠. 이게 이제 로컬 PC에서 해서 다행이지 실제 운영 서버에서 하면 이제 바로 장애가 나는 거죠. 문제가 될 수 있죠.

근데 이게 또 왜 문제가 되냐면 toString 뿐만 아니라 JSON 생성 라이브러리 같은 데서도 이거를 쭉 다 뽑아버려요. 그러면서 양방향이 걸려 있으면 엔티티를 JSON으로 바꾸는 순간 그냥 무한 루프에 빠져버리는 거죠. 그러면서 스택 오버플로우가 나거나, 장애가 나거나 하겠죠.

그래서 사실 JSON 생성 라이브러리가 언제 실제 운영에서 문제가 생기냐면 직접 컨트롤러에서 엔티티를 직접 보내버리면 이 엔티티가 가진 연관관계가 양방향으로 걸려있으면 그때 예를 들어서 스프링 많이 쓰시니까 컨트롤러에서 엔티티를 바로 반영하면 그 엔티티를 JSON으로 바꿀 때 이제 보니까 예를 들어서 Member면 'Team이 있네?' 또 Team을 또 JSON으로 하는데 'members가 있네?' 그러면 또 members를 하니까 이렇게 계속 파고 들어가는 거예요. 그러면서 장애가 나는 거죠. 사실 이거는 답이 정해져 있어요.
뭐냐면 일단 Lombok에서 toString 만드는 거눈 웬만하면 쓰지 마라. 혹시 쓰더라도 저런 거는 빼고 써라. 라고 이제 말씀드리고요.
근데 JSON 생성 라이브러리는 크게 걱정할 필요가 없는 게 컨트롤러 실제 JPA로 실무하시는 분들이 질문을 많이 해주세요. 그냥 제가 답을 드릴게요. 컨트롤러에서는 엔티티를 절대 반환하지 마세요.
왜냐하면 컨트롤러에서 엔티티를 반환하면 스프링이 요즘 잘 해주니까 엔티티를 JSON으로 쫙 뽑잖아요. 요즘에는 거의 JSON으로 통신하면서 업무를 하니까 컨트롤러에서 엔티티 자체를 json으로 api 스펙에 반환을 해버리면 두가지 문제가 생겨요.
첫번째 이런 무한 루프가 생길 수도 있고, 두번째는 엔티티는 충분히 변경될 수 있잖아요. 여러가지 이유로 필드가 추가될 수도 있고. 그런데 엔티티를 api에 반환을 해버리면 나중에 그 엔티티를 변경하는 순간 그 api 스펙이 바뀌어 버리는거에요. 그러니까 api를 갖다 쓰는 입장에서 황당하겠죠. 내가 직접 컨트롤 하는 거라 그래도 문제가 될 여지가 되게 커요. 그래서 Entity는 웬만하면 DTO라고 그러죠. 이제 정말 그냥 단순하게 값만 있는 DTO로 변환을 해서 컨트롤러에서 엔티티가 아니라, DTO를 반환하는 거를 추천드려요. 그렇게 하면 이 json 생성 라이브러리로 인한 문제가 거의 없어요. 값이 나갈 때 들어올 때 다 마찬가지고요.
지금은 사실 예제여서 그냥 뒤에도 엔티티를 반환하고 할 텐데 실제 실무에서는 웬만하면 컨트롤러에서 엔티티를 반환하지 마세요. 그것만 안 해도 대부분의 많은 문제가 해결이 됩니다. 이렇게 강의하면서 제가 중간중간에 실무에서 꼭 필요한 내용들, 그리고 실무에서 질문이 많이 들어오는 내용들도 계속 소개를 해드릴게요.

이제 정리를 해보겠습니다. 단방향 맵핑만으로도 이미 연관관계 맵핑은 완료가 다 된 거에요. 양방향 맵핑을 지금 정리하는데 여러분 이게 지금 엄청 중요해요. 사실 여러분 그 JPA 모델링 하실 때 단방향 맵핑으로 처음에 설계를 끝내야 돼요. 양방향 맵핑 하시면 안 돼요.
처음에 설계를 할 때 주문 시스템이라고 하면 오더나 연관된 테이블들이 엄청 많잖아요. 실제 실무에 보면 테이블 20-30개 이상은 나오죠.

jpa을 딱 쓰신다고 하고 설계를 들어가잖아요. 그러면 일단 단방향 맵핑으로 설계를 완료해야 돼요. 그러니까 뭐냐면 실무에서는 사실 정말 객체만으로 설계할 수 있냐, 저는 아니라고 보거든요. 테이블 설계를 어느 정도 머리에 계속 그리면서 객체 설계를 같이 들어가야 되거든요. 그럼 그 시점에 테이블 관계에서 대략적인 Foreign Key가 다 나와요. 어디에 외래키를 둘지. 왜냐면 일대다 이런 관계가 나오니까. 그럼 결국 다 쪽에서 단방향 맵핑을 @ManyToOne이나, @OneToMany로 걸어서 들어가야 되는데 이때 양방향 맵핑을 하지 마세요. 처음에는 무조건 단방향 맵핑으로 일단 설계를 끝내야 돼요. 그리고 나서 앞쪽에서 말씀드렸듯이, 양방향 맵핑은 반대 방향으로 조회 기능이 추가되는 거거든요. 결과적으로 db 테이블의 설계, 그리고 jpa에서의 설계라는 것은 객체랑 테이블을 맵핑하는 것은 단방향 맵핑만으로 이미 완료가 된 거예요. 사실 테이블은 한 번 만들어지면 굳어지잖아요. 그리고 객체 입장에서는 양방향으로 설계해도 좋을 게 별로 없어요. 아까처럼 연관관계 편의 메서드도 만들어야 되고 고민거리만 많아지는 거예요. 그러니까 설계하는 입장에서만 보면 테이블이랑 객체를 맵핑한다는 관점에서만 보면 사실 단방향 맵핑만으로도 이미 설계가 다 끝난 거예요. 그러면 양방향 맵핑이 언제 들어가냐? 그 반대쪽, 일대다 맵핑이 언제 들어가냐면 생각보다 실무에서는 문제가 역방향으로 참조할 일이 좀 많아요. 막상 나중에 JPQL 쿼리를 막 짜가지고 들어가야 될 일이 많거든요. 그래서 이제 실무에서 하시다 보면은 양방향으로 탐색해야 될 일이 많아요. 그래서 중요한 게 단방향 맵핑만 잘 해두면 양방향 맵핑은 필요할 때 추가하면 돼요. 잘 보시면 테이블에 손댈 필요 없이 엔티티의 코드 몇 줄만 넣으면 돼요.
이전에 제가 보여드렸듯이 다시 볼게요.

이 단방향 연관관계에서 보시면 이 테이블을

제가 이 양방향 연관관계로 중간에 바꿨는데요. 보시면 이 Team 객체는 List members 컬렉션만 하나 더 넣어줬지 테이블은 전혀 손댄 게 없잖아요. 그래서 무슨 말이냐면,

다시 돌아와서 단방향 맵핑을 잘 하고 일대다 양방향 매핑, mappedBy로 넣은 애는 꼭 필요할 때 중간에 추가하셔도 됩니다. 왜냐하면 테이블에 영향을 주지 않거든요. 사실 자바 코드 몇 줄 넣는 건 어렵지 않잖아요. 그래서 정말 필요하다 싶으면 고민하셔서 넣으시면 돼요. 기본적으로 딱 생각을 어떻게 가져가야 되냐면 단방향 맵핑으로 다 끝낸다. 일대다에서 다인 방향에다 그냥 다 연관관계 매핑을 쫙 해서 단방향 맵핑을 발라주고 설계를 쫙 끝낸 다음에 실제 애플리케이션 개발하는 단계에 들어가서 양방향 맵핑은 그때 고민하셔도 늦지 않아요.
다시 말씀드리지만 객체 입장에서 볼 때 양방향 맵핑이라는 게 별로 크게 이득이 많이 되는게 없어요. 아무튼 저는 이렇게 정리를 해드리고요.
연관관계의 주인을 정하는 기준은,

다시 강조드리지만, 비즈니스 로직을 기준으로 연관관계 주인을 선택하면 안됩니다. 물론 할 수는 있어요. '비즈니스적으로 이게 중요하니까 얘를 연관관계 주인으로 정할 거야'라고 할 수 있어요. 근데 그게 중요한 게 아니고, 진짜 중요한 거는 연관관계 주인은 외래 키의 위치를 기준으로 정해야 됩니다. 이렇게 해야 사실 jpa 처음 시작하시는 분들도 어렵지 않고 성능이나 뭐 여러가지 운영 관점에서 볼 때도 이게 훨씬 더 이득이 많아요. 그래서 연관관계 주인은 외래 키의 위치를 기준으로 정하시면 됩니다. 이러면 헷갈릴 게 하나도 없어요.
db 설계를 딱 생각했을 때 '아 외래키가 들어가네' 그럼 얘를 연관관계 주인으로 딱 정하면 돼요. 그러면 고민거리가 싹 사라져요. 그리고 뭔가 객체 입장에서 볼 때는 예를 들어서 @OneToMany 있는 그쪽 예제코드에서 Team 쪽에 뭔가 넣고 싶다 그러면 그때는 연관관계 편의 메서드를 활용하는 거예요.

이런 식으로 푸시면 돼요.

그래서 사람들이 이걸 호출하기 위해서 설계를 해두면 돼요.

그래서 'Team의 룰을 정합니다. Team에서 Member를 집어 넣을 때는 이 메서드를 호출하세요' 라고 해서 딱 정해놓으면 돼요. 그렇게 하면 연관관계 주인은 주인대로 잘 정하고 객체를 풀 때 Team에다가 Member를 넣는 식으로 설계를 하고 싶다고 하면 방금처럼 연관관계 편의 메서드를 푸시면 돼요.

그래서 제일 중요한 기준을 제가 정해드렸습니다.

그럼 여기까지 하고요. 다음 시간에는 실전 예제 2번을 할 건데, 이전 실전 예제 1번은 단순하게 연관관계 맵핑을 안 배웠으니까 PK랑 Foreign Key 값만 가지고 했었죠.
이제 다음 시간에는 연관관계를 바꾸는 걸로 한번 해보겠습니다.
'스프링 > 자바 ORM 표준 JPA 프로그래밍 - 기본편' 카테고리의 다른 글
| 다대일 [N:1] (0) | 2024.06.21 |
|---|---|
| 실전 예제 2 - 연관관계 매핑 시작 (0) | 2024.06.19 |
| 양방향 연관관계와 연관관계의 주인 1- 기본 (0) | 2024.06.10 |
| 단방향 연관관계 (0) | 2024.06.10 |
| 실전 예제 1 - 요구사항 분석과 기본 매핑 (0) | 2024.06.08 |