소개
게시글
질문&답변
@JoinColumn 질문 :]
DB 테이블 기준으로 생각하시면 됩니다.MEMBER 테이블의 외래키 TEAM_ID 컬럼을 선택하는거예요. 자바 클래스와는 무관합니다
- 0
- 1
- 332
질문&답변
벌크 연산, 영속성 컨텍스트 후 member.getAge() 조회 결과 질문드립니다!
Member member1 = memberRepository.findById(memberId) // 멤버의 age는 0 em.createQuery("update ~~") // 벌크 업데이트 em.clear() //영속성 컨텍스트 초기화 System.out.println(member1.getAge()) // 0 출력이런 상황으로 이해하면 될까요?
- 3
- 2
- 245
질문&답변
연관관계 주인 관련 질문 드립니다.
1. 가장 기본적인 문제는 테이블 정의부터가 제대로 안 됩니다.이해하신 것처럼 DB는 외래키 하나로 양방향이 가능한데, 객체는 단방향 참조 두 개로 이를 흉내냅니다.반대로 양방향으로 연결되도록 엔티티를 설계하면 DB입장에서는 이게 하나의 연관관계를 양방향으로 흉내낸건지 두 개의 연관관계가 필요한건지 모르게 됩니다. 실제로 강의에 나온 Member와 Team 예제에 있어서, mappedBy를 넣지 않고 ddl-auto crreate로 돌려보시면 team -> member 일대다 연관관계를 맵핑하기 위한 테이블이 하나 더 추가로 생성됩니다. Hibernate: create table member (member_id bigint not null, team_id bigint, primary key (member_id))Hibernate: create table team (team_id bigint not null, primary key (team_id))Hibernate: create table team_team (team_team_id bigint not null, team_member_id bigint not null 연관관계의 주인 개념이 있어야 우리가 설정한 양방향 관계가 TABLE 개념에서의 연관관계 하나임을 보장할 수 있습니다.2. 영속성 컨텍스트 변경감지 기준member.setTeam(), team.addMember()를 모두 허용하게 되면 영속성 컨텍스트가 너무 복잡해집니다. 경우에 따라서 update 쿼리가 두 번 나가게 될 수 있고 (양쪽 연관관계가 모두 업데이트 된 경우), 이를 최적화하기 위한 추가적인 연산도 많을 것 입니다. 또한 양쪽 연관관계가 모순되는 경우에는 어떻게 처리할지에 대한 규약도 훨씬 복잡해집니다.예컨대 team.members에는 member1이 있는 상태에서 member1.setTeam(null) 을 한 경우 어느쪽을 따라야 하는가? 등등..
- 0
- 1
- 255
질문&답변
지연 로딩 update 시
JPA와 하이버네이트의 구현과는 관계 없이 일반적으로 지연로딩은 조회와 깊은 관련이 있는 개념입니다. 말 그대로 조회가 필요한 시점까지 조회를 늦추겠다는 개념이기 때문입니다. 조회한 객체를 수정하는 것은 지연로딩과는 관련이 없는 개념으로, 지연로딩이든 아니든 영속성 컨텍스트 변경감지는 똑같이 이루어집니다. 마지막으로, update 쿼리는MEMBER에밖에 나갈 수 없는 구조입니다. MEMBER가 TEAM의 외래키를 들고 있기 때문입니다. (TEAM쪽에 update를 해서 member와의 연관관계를 규정할 방법이 없습니다)연관관계에 대한 영속성 컨텍스트의 변경감지는 연관관계의 주인 쪽에서만 일어납니다.MEMBER가 주인이라면 member.setTeam 이 update 쿼리를 발동시킬것이고, TEAM이 주인이라면 team.addMember()가 update 쿼리를 발동시킬 것입니다.연관관계의 주인 강의를 보시면 이해가 가실거예요
- 0
- 1
- 202
질문&답변
연관관계 주인 위배?
연관관계의 주인 개념은 영속성 컨텍스트에게 어느쪽이 연관관계를 관리하는 주인 역할을 하는지 알려주는 개념이고, CASCADE는 PERSIST, REMOVE 등의 특정 액션이 엔티티에 걸릴 때 자식 엔티티에도 같은 액션을 "전파"시켜주는지만 신경쓰는 개념입니다. 강의에 나온 Member와 Team을 예시로 하겠습니다. Team team = new Team(); team.add(new Memeber()); em.persist(team); 위 코드만 있을 시 CASCADE 옵션이 없다면 연관관계가 TEAM 쪽으로 잡혀있다고 하더라도 멤버는 영속성 컨텍스트에 등록되지 않습니다. CASCADE 옵션이 위 코드에서 하는 역할은 em.persist(team)을 해줬을때 team 객체 안의 자식객체들을 찾아서 자식객체 또한 자동으로 persist를 해주는 것일 뿐입니다. 개념적으로는 이렇게 연관관계와는 별개의 개념이지만, CASCADE 옵션을 그냥 마구잡이로 편한대로 쓰다보면 DB관리가 크게 잘못될 수 있기 때문에 생명주기가 명확한 객체끼리 붙이게 되고, 그러다보니 연관관계 개념과 섞여서 혼동스러울 수 있는 개념인 것 같습니다.
- 1
- 1
- 300
질문&답변
업데이트 쿼리가 마지막에 나가는 이유를 모르겠습니다.
OrderItem이 영속화되는 시점에 Item은 비영속 상태이기 때문입니다.미리 setItem은 해두혔어도 item 객체의 고유식별자가 없기 때문에 해당 시점에 영속성컨텍스트에 관리를 해줄 수 가 없습니다.추후 em.persist(item)을 하게 되면 비로소 item이 영속상태가 되고 변경감지가 일어납니다.
- 1
- 1
- 183
고민있어요
질문글에 다른 학생이 직접 답변하는 경우에도 강사님이 한번 체크하시나요?
- 1
- 2
- 119
질문&답변
패치조인과 일반 조인 질문있습니다
연관된 엔티티를 조회할 일이 있더라도 지연로딩하는게 성능상 이점이 있을 경우에는 fetch join을 하면 안됩니다. 비즈니스 로직에 따라서 어떻게 하는게 좋을지 그때그때 상황 봐서 판단하는게 좋겠습니다
- 1
- 2
- 174
질문&답변
연관관계 편의메서드 .
2. 일대다에서 fetch join 을 하면 데이터가 뻥튀기되는 이유는 fetch join 때문이 아니고 SQL 문 실행 자체가 그렇게 되기 때문입니다. 위의 fetch join 는 결국 inner join SQL문을 실행시키고 다음과 같은 결과물을 뽑습니다. (TeamA의 ID는 1, member의 id는 각각 1, 2라 가정) TEAM_ID, MEMBER_ID 1, 1 1, 2 즉 team은 하나밖에 없는데 멤버수만큼 row수가 뻥튀기되서 결과물이 나오게 됩니다. 일반적인 페이징 방식으로 첫 번째 레코드만 뽑는다고 하면, 위의 결과물에 첫번째 레코드만 반환을 하게 되는데 그렇게 되면 teamA에 멤버1밖에 딸려나오지 않습니다. 사용자의 의도와는 다른 결과물이 나오게 되지요. 따라서 DB단계에서의 최적화를 기대할 수 없기 때문에 DB에서 모든 데이터를 다 조회하고 메모리에서 추려내는 수밖에 없게 됩니다. 위에서는 멤버가 둘 밖에 없어서 괜찮았지만 멤버가 1000만명이었다면, 첫 1개만 뽑고싶어도 DB에서는 1000만개의 레코드를 전부 조회해서 가져온다음에 메모리 상에서 첫 1개만 추려내게 되기 때문에 의도와는 다르게 굉장히 무거운 작업이 되어버립니다. 결과적으로 말하자면, 위험하다는 기준이 의도와는 다른 잘못된 데이터를 가져올까봐 위험하다는것이 아닌 내 의도와는 다른 매우 무거운 작업이 될 확률이 매우 농후하다는 점에서 위험한 코드가 되겠습니다
- 2
- 2
- 415
질문&답변
연관관계 편의메서드 .
1. 당연히 member에 team을 연결하고 나면, 추후 em.find()로 team을 가져왔을 시 team.getMembers()에 잘 반영이 되게 됩니다. 강의에서 설명하고자 했던 부분은 한 트랜잭션이 끝나기 전에는, 논리적으로는 member에 team이 들어가면 자동적으로 team에 member도 추가되어야 정상이지만 그런 효과를 단순 setter로만 누릴수는 없기 때문에 매번 member.setTeam(team), team.addMember(member) 하는게 귀찮다면 두 개 기능을 합친 메서드를 만들면 편하다는 얘기를 하신 것 같습니다
- 2
- 2
- 415