월 24,200원
5개월 할부 시다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 해결됨자바 ORM 표준 JPA 프로그래밍 - 기본편
강의를 보다가 해당 어노테이션 속성 목록들 보는 단축키
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오) 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 아니요3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)예[질문 내용]여기에 질문 내용을 남겨주세요. 해당 어노테이션 목록 띄우는 키가 있을까요? ctrl로 들어가서 봐야 하는걸까요?ctrl + space로 했었던 거 같은데 안되네요~key 에서 code는 ctrl + space로 되어있습니다
- 미해결자바 ORM 표준 JPA 프로그래밍 - 기본편
페치조인 질문 있습니다
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오) 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) 예[질문 내용]여기에 질문 내용을 남겨주세요. 페치 조인으로 데이터를 가져왔을때예를들어 EntityA 와 EntityB 가 1:1관계이고 EntityB와 EntityC가 1:N관계일때select a from EntityA a join fetch EntityB 이런식으로 가져왔습니다. 근데 EntityB안에 EntityC가 @oneToMany로 있을 때현재 저대로 쿼리를 날리면 EntityB를 통해서 EntityC에 접근할때마다 쿼리가 날라갑니다EntityA를 조회하는 시점 ( select a from EntityA a join fetch EntityB )에 EntityC까지 한번에 페치조인으로 가져올 순 없는 걸까요?
- 미해결자바 ORM 표준 JPA 프로그래밍 - 기본편
자바 ORM 표준 JPA - 10.객체지향 쿼리언어1-기본문법 관련 질문
=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]조인 부분 설명해주실때요 조인 대상 필터링 부분에서 JPQL 로 쿼리문 작성할때 select m,t from Member m left join m.team t on ~이런 식으로 작성하시는데 저기서 Team t 라고 못쓰고 꼭 m.team t 라고 써야되는건가요??? 연관관계없는 엔티티 외부 조인 부분 JPQL 쿼리문 작성하실땐 select m,t from Member m left join Team t on~ 이런식으로 작성하셨는데 여기서는 m.team t 로 쓰면 안되고 Team t 이런식으로 쓰는 건가요???
- 해결됨자바 ORM 표준 JPA 프로그래밍 - 기본편
강의 7분 50초 쯤에 질문있습니다.
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]테이블 생성에서 SQL을 보시는데 Member 테이블 쿼리에 FAVORITE_FOOD와 ADDRESS 에 대한 정보가 아무것도 없는데 그럼 어떻게 저 둘과 연결시키나요?
- 미해결자바 ORM 표준 JPA 프로그래밍 - 기본편
자바 ORM 표준 JPA 프로그래밍 - 9.값 타입 강의 관련 질문
=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]값 타입 컬렉션 부분 설명해주실때 기본적으로 컬렉션은 remove의 대상을 찾을때 equals를 사용한다고 하셨는데요member.get~History().remove(new Address(~~));에서 만약 Address 클래스에서 equals 메서드를 오버라이딩 하지 않았다면 Object 의 equals 메서드를 사용하는건가요??
- 미해결자바 ORM 표준 JPA 프로그래밍 - 기본편
hibernate.properties not found 오류 안고쳐짐
아무리 인터넷에 나와있는대로 pom.xml 파일에 <dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> <version>2.3.1</version> </dependency>아래 코드를 추가해보아도 뭘 해도 저 오류가 없어지지 않습니다. 무엇이 문제일까요.... 다른 해결방법이 또 있을까요? java17 버전 입니다.
- 해결됨자바 ORM 표준 JPA 프로그래밍 - 기본편
무조건적인 @Transactional?
@Service @RequiredArgsConstructor public class SignUpMemberService implements SignUpMemberUseCase { private final MemberRepository memberRepository; @Override public Long invoke(final Command command) { validateEmailIsUnique(command.email()); validateNicknameIsUnique(command.nickname()); validatePhoneIsUnique(command.phone()); final Member member = command.toDomain(); return memberRepository.save(member).getId(); } } @Service @Transactional @RequiredArgsConstructor public class SignUpMemberService implements SignUpMemberUseCase { private final MemberRepository memberRepository; @Override public Long invoke(final Command command) { validateEmailIsUnique(command.email()); validateNicknameIsUnique(command.nickname()); validatePhoneIsUnique(command.phone()); final Member member = command.toDomain(); return memberRepository.save(member).getId(); } }사용자 가입 UseCase에 대한 구현에서 앞단에서는 unique field에 대한 validation을 진행합니다그 후에 memberRepository.save(member)를 진행하는데 (memberRepository는 Data Jpa Repo)아시다시피 SimpleJpaRepository의 save흐름에는 @Transactional이 적용되어 있습니다따라서 이 SignUpMemberService의 invoke 흐름부터 굳이 @Transactional을 걸어야 하는 생각이 듭니다물론 붙임으로써 이 메소드가 writable한 로직을 가진다고 코드레벨에서 알고 JPA를 모르는사람은 SimpleJpaRepository의 구조를 모르기 때문에 가독성?적인 측면에서는 붙이는게 이해에 수월하다고 생각하는데 tx scope를 최대한 짧게 가져가는게 좋다는 생각이 들어서 약간의 고민을 하게 되었습니다
- 미해결자바 ORM 표준 JPA 프로그래밍 - 기본편
자바 ORM 표준 JPA 프로그래밍 기본 - 8.프록시와 연관관계 관리
=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]즉시로딩과 지연로딩 파트 설명해주실때 질문이 있습니다.fetch = FetchType.LAZY)로 지연로딩을 사용해서 프록시로 조회한다고 하시면서 코드로 설명해 주실때Team만들고 em.persist(team);Member 만들고 em.persist(member);em.flush();em.clear();Member m = em.find(~~);m.getTeam().getName();이 부분에서 마지막 m.getTeam().getName(); 이 부분할때 db에 쿼리가 나간다고 하셨는데 왜 쿼리가 나가는 건가요?? em.find로 db에서 찾은 객체가 영속성 컨텍스트에 올라와 있어서 쿼리문을 안날려도 되는거 아닌가요?? 그리고 지연로딩할때 Member클래스의 Team 필드에만 지연로딩을 적용했는데 JpaMain 클래스에서 em.find(Member.class,~~);로 객체 찾을때 이 Member 클래스 자체가 프록시가 되는건가요???
- 미해결자바 ORM 표준 JPA 프로그래밍 - 기본편
자바 ORM 표준 JPA 프로그래밍 기본 - 8.프록시와 연관관계 관리
=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]8.프록시와 연관관계 관리 강의 중에서 프록시 부분 설명하실때 이해가 안되는 부분이 있는데요em.getReference()하면 프록시 객체가 영속성 컨테스트에 생성되는 건가요??JpaMain 클래스에서 코드 작성하실때Member member1 = new Member();member1.setUsername("member1");em.persist(member1);em.flush();em.clear();Member refMember = em.getReference(~,member1.getId());refMember.getUsername();이렇게 작성하셨는데 아래쪽에 프록시 객체 생성하고 refMember.getUsername()할때 왜 db에 select문이 나가는 건가요??영속성 컨텍스트에 없어서 그런건가요???그리고 위의 코드에서 refMember.getUsername(); 할때 프록시를 초기화 한다고 하셨는데 getter 메서드쓰는게 어떻게 초기화를 하는건가요??프록시에 getUsername()을 하면 프록시에 username 값이 세팅되는 건가요?? 프록시는 target 이랑 진짜 객체의 메소드만 갖고있는거 아닌가요???
- 해결됨자바 ORM 표준 JPA 프로그래밍 - 기본편
즉시로딩의 문제점
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]강의 15분에 즉시로딩의 문제점에서 JPQL의 N+1문제점에서 쿼리가 2번나가면 문제가 발생하는 이유가 있나요?? 데이터 잘 들어오는거 같은데 성능문제인가요?? 근데 어차피 지연 로딩하면 쿼리가 2번 나가게 되는거아닌가요?
- 해결됨자바 ORM 표준 JPA 프로그래밍 - 기본편
@transactional 어노테이션
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]@transactional 어노테이션을 메소드에 붙여주면 강의의 Main에 코드에 있는 아래 코드 부분이 자동화 해주는 것인가요?EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello"); EntityManager em = emf.createEntityManager(); EntityTransaction tx = em.getTransaction(); tx.begin(); try { tx.commit(); } catch (Exception e) { tx.rollback(); } finally { em.close(); } emf.close();
- 해결됨자바 ORM 표준 JPA 프로그래밍 - 기본편
테이블 생성 순서중 id 값 ( Pk)
테이블 ddl create 로 자동 생성할때강사님은 id 값 생성은 무조건 순서 1번째 컬럼으로 가는데저는 그거 상관없이 무조건 알파벳 순이네요 pk포함버전에 따른 문제인건가요?방법은 없을까요아래는 제 버전입니다. <!-- JPA 하이버네이트 --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>6.2.7.Final</version> </dependency> <!-- H2 데이터베이스 --> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <version>1.4.200</version> </dependency> @Entity public class Member { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE) private Long id; @Column(name = "name", length = 30, nullable = false) private String username; @Column private int age; 이렇게 했을때 테이블 create 결과는 이렇구요,근데 정말 신기한건 만약 age 를 int 에서 String 타입으로 바꾸면 뒤로 밀리네요이게 타입별로 먼저 정렬하고 그 뒤에 알파벳인거같기도하고왜 그런걸까요?뭐 솔직히 실무에서는 중요한 내용은 아닌거 같은데강사님 버전 타입이랑 달라서 궁금합니다.그리고 테이블 순서에대한 내용은 hibernate 문서를 보면 되는걸까요?문서를보고 직접 확인해보고싶네용
- 해결됨자바 ORM 표준 JPA 프로그래밍 - 기본편
MappedSuperClass 사용 기준
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]MappedSuperclass도 결국 상속 받는거고이전 예시의 Item도 결국 값, 이름만 상속해서 결국 공통정보를 사용하는거 같은데어느상황에서 MappedSuperclass를 사용하고 어떨 때 상속을 받아 사용하는지 궁금합니다.MappedSuperclass를 사용하면 결국 디비는 다르다는게 결국은 단일테이블 전략으로 상속하는거랑 비슷한거 아닌가요??
- 해결됨자바 ORM 표준 JPA 프로그래밍 - 기본편
일대다 매핑시 질문있습니다.
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]@Entity public class MemberProduct { @Id @GeneratedValue private Long id; @ManyToOne @JoinColumn(name = "MEMBER_ID") private Member member;강좌 9분에 작성하시는 위 코드에서 @ManyToOne 코드에서 JoinColum(name = "") 이 부분의 name속성은 MemberProduct의 디비에 칼럼 이름을 지정하는 것이고 디비 자체에서 외래 키(MEMBER_ID)가 어느 엔티티와 연결되었느냐는 바로 밑의코드 private Member member; 이 부분을 보고 Member 클래스도 Entity 이기 때문에 member와 연결시키는 쿼리를 작성해주는건가요??
- 해결됨자바 ORM 표준 JPA 프로그래밍 - 기본편
강의 16분
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]강의 16분에 정리하실 때 주 테이블이냐 대상 테이블이냐는 비즈니스 로직에 따라 즉 개발자가 선택하기 나름인거죠?? 기준이 있나요??
- 해결됨자바 ORM 표준 JPA 프로그래밍 - 기본편
@JoinColumn 질문
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]1. 강의 4분 36초 쯤의 @JoinColumn에 name 속성인 LOCKER_ID는 디비의 MEMBER테이블의 LOCKER_ID 칼럼이라는 뜻인가요 아니면 Locker Id를 Column(name = "LOCKER_ID")라고 했을 때 여기있는 LOCKER_ID를 나타내는 것인가요?
- 해결됨자바 ORM 표준 JPA 프로그래밍 - 기본편
객체가 스스로의 리스트를 가지고, 양방향 매핑을 해도 될까요?
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]악! 스프링 웹 개발은 즐거워! 김영한 선생님 질문있습니다.선생님의 두 로드맵을 거의 다 듣고 그를 바탕으로 포폴용 게시판을 만들어보고 있습니다. 와중 댓글과 대댓글 기능을 구현하는 과정에서 Comment라는 객체를 만들고 객체의 타입을 Comment와 reply로 나누었습니다. 특정 게시판에 관한 데이터를 불러올 때 댓글과 대댓글을 편리하게 불러오기 위해 타입이 Comment인 객체가 reply에 해당하는 객체를 리스트로 갖도록 설계했습니다. 이후 테스트를 진행해보았는데 fetch join을 통한 데이터 로드는 문제 없이 진행되었습니다. 다만 이러한 설계 방식이 올바른지에 대한 질문을 스스로 해결할 수 없어서 글 남깁니다. 아래는 코드와 테스트 코드 및 실행 결과이고, 마지막에 질문이 있습니다.package toy.board.domain.post; import jakarta.persistence.*; import jakarta.validation.constraints.NotNull; import java.util.ArrayList; import java.util.List; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.NoArgsConstructor; import org.springframework.util.StringUtils; import toy.board.domain.BaseDeleteEntity; import toy.board.domain.user.Member; @Entity @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor(access = AccessLevel.PROTECTED) @EqualsAndHashCode(callSuper = true) public class Comment extends BaseDeleteEntity { public static final int CONTENT_LENGTH = 1000; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "comment_id", nullable = false) private Long id; @Column(name = "content", nullable = false, length = CONTENT_LENGTH) private String content; @Column(name = "type", nullable = false, updatable = false) private CommentType type; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "post_id", nullable = false, updatable = false) private Post post; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "member_id", nullable = false, updatable = false) private Member member; @OneToMany(mappedBy = "parent") private List<Comment> replies = new ArrayList<>(); @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "parent_comment_id", updatable = false) private Comment parent; /** * 양방향 관계인 Member와 Post에 대해 자동으로 양방향 매핑을 수행한다. */ public Comment( @NotNull final Post post, @NotNull final Member member, @NotNull final String content, @NotNull final CommentType type ) { this.post = post; this.member = member; this.content = content; this.type = type; } public boolean update(final String content) { if (!StringUtils.hasText(content)) { return false; } this.content = content; return true; } public void leaveReply(Comment reply) { if (areTypesCorrectThisAnd(reply)) { throw new IllegalArgumentException("주어진 댓글과 대댓글의 타입이 올바르지 않습니다."); } if (hasComment(reply)) { throw new IllegalArgumentException("대댓글이 이미 다른 댓글에 포섭되어 있습니다."); } if (isNew(reply)) { throw new IllegalArgumentException("댓글이 이미 해당 대댓글을 포함하고 있습니다."); } this.replies.add(reply); reply.parent = this; } private boolean isNew(Comment reply) { return this.replies.contains(reply); } private static boolean hasComment(Comment reply) { return reply.parent != null; } private boolean areTypesCorrectThisAnd(Comment reply) { return this.type != CommentType.COMMENT || reply.type != CommentType.REPLY; } } @Transactional @DisplayName("comment가 List<comment>를 갖고, fetch join으로 가져올 수 있는가?") @Test public void comment_has_comments_fetch_join() throws Exception { //given Member member = Member.builder( "member", new Login("password"), Profile.builder("nickname").build(), LoginType.LOCAL_LOGIN, UserRole.USER ).build(); em.persist(member); Post post = new Post(member, "title", "content"); em.persist(post); Comment comment = new Comment(post, member, "comment", CommentType.COMMENT); em.persist(comment); for (int i = 0; i < 5; i++) { Comment reply = new Comment(post, member, "reply" + String.valueOf(i), CommentType.REPLY); comment.leaveReply(reply); em.persist(reply); } em.flush(); em.clear(); //when QComment reply = new QComment("reply"); List<Comment> findComments = queryFactory .selectFrom(QComment.comment) .leftJoin(QComment.comment.replies, reply).fetchJoin() .where( QComment.comment.post.id.eq(post.getId()), QComment.comment.type.eq(CommentType.COMMENT) ) .fetch(); System.out.println("============================================="); for (Comment findComment : findComments) { System.out.println("findComment.getId() = " + findComment.getId()); System.out.println("findComment.getContent() = " + findComment.getContent()); } //then Comment findComment = findComments.get(0); for (Comment findReply : findComment.getReplies()) { System.out.println("findReply content = " + findReply.getContent()); } }[테스트 실행 시 create query]create table comment ( is_deleted boolean default false not null, type tinyint not null check (type between 0 and 1), comment_id bigint generated by default as identity, created_date timestamp(6), deleted_date timestamp(6), last_modified_date timestamp(6), member_id bigint not null, parent_comment_id bigint, post_id bigint not null, content varchar(1000) not null, created_by varchar(255), last_modified_by varchar(255), primary key (comment_id) )[테스트 실행 결과] select c1_0.comment_id, c1_0.content, c1_0.created_by, c1_0.created_date, c1_0.deleted_date, c1_0.is_deleted, c1_0.last_modified_by, c1_0.last_modified_date, c1_0.member_id, c1_0.parent_comment_id, c1_0.post_id, r1_0.parent_comment_id, r1_0.comment_id, r1_0.content, r1_0.created_by, r1_0.created_date, r1_0.deleted_date, r1_0.is_deleted, r1_0.last_modified_by, r1_0.last_modified_date, r1_0.member_id, r1_0.post_id, r1_0.type, c1_0.type from comment c1_0 left join comment r1_0 on c1_0.comment_id=r1_0.parent_comment_id where c1_0.post_id=? and c1_0.type=?=====================findComment.getId() = 1findComment.getContent() = commentfindReply content = reply0findReply content = reply1findReply content = reply2findReply content = reply3findReply content = reply4 [질문]제가 궁금한 것을 자세히 말하자면,테이블이 만들어질 때, comment 테이블의 특정 row(대댓글인 컬럼)가 해당 테이블의 다른 row(댓글인 row)의 PK값을 FK로 갖는데, 댓글에 해당하는 row는 객체가 생성되고 DB에 저장될 때 해당 컬럼에 null이 저장됩니다. 이는 Comment 객체의 ID에 @GenerateValue 설정을 주어서 그렇습니다. 위의 상황은 실무에서 사용할만큼 적절한가요? 아니라면 대안이 있을까요?jpa와 관련된 질문을 읽다보니, 다대일 관계에서 left join fetch의 경우 where문의 결과에 따라 데이터 일관성의 오류가 나타날 수 있다는 답변이 있었습니다.(해당 글: https://www.inflearn.com/questions/15876/fetch-join-%EC%8B%9C-%EB%B3%84%EC%B9%AD%EA%B4%80%EB%A0%A8-%EC%A7%88%EB%AC%B8%EC%9E%85%EB%8B%88%EB%8B%A4) 제가 작성한 테스트 코드의 쿼리문은 일대다 관계에서 일에 해당하는 엔티티에 별칭을 주어 where문을 적용한 것이므로 일관성의 문제가 발생하지 않는다고 생각했는데 이것이 옳은 생각인가요? 마지막으로 쿼리의 복잡도와 쿼리 개수는 trade off 관점에서, 특정 게시물에 관한 데이터를 반환해야 하는 api 요청이 들어왔을 때, 게시물과 댓글 엔티티가 단방향 관계일 경우 게시물에 관한 데이터와 댓글 및 대댓글에 관한 데이터를 각각의 저장소를 통해 가져오는 것이 좋을까요 혹은 쿼리가 다소 복잡해지더라도 한 번에 가져오는 것이 좋을까요? 아니면 단방향 관계를 양방향으로 만드는 것이 더 나은 선택일까요? 혼자 공부하니 올바른 방식을 찾는게 참으로 어려운 것 같습니다.답변 기다리겠습니다. 감사합니다.
- 미해결자바 ORM 표준 JPA 프로그래밍 - 기본편
ORDERS와 ORDER_ITEM 테이블 두개가 존재하는 이유
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]안녕하세요 테이블 구조에 대해 의문이 들어서 글 남기게 되었습니다MEMBER 테이블과 ITEM 이 N:M 관계이고 그렇기 때문에 주문(MEMBER_ITEM) 이라는 관계 테이블을 이용해서 MEMBER와 ITEM 간의 N:M 관계를 표현해주면 안되나요?ORDERS 라는 테이블이 존재하는 이유를 모르겠습니다..
- 해결됨자바 ORM 표준 JPA 프로그래밍 - 기본편
양방향 통신에서의 주인
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]양방향 통신에서 member를 주인으로 하셨는데 예를들어 memberA의 팀이 TeamA였는데 TeamB로 변경할 때 Team entity의 memberList(members)는 읽기만 해야한다고 하셨는데 그러면 memberA.setTeam("TeamB")를 해주고 쿼리를 날리면 디비에서 자동으로 참조해서 바꿔주고 객체의 TeamA의 memberList에 있는 memberA를 삭제하고 TeamB의 memberList에 memberA를 추가해주나요??
- 해결됨자바 ORM 표준 JPA 프로그래밍 - 기본편
양뱡향 통신의 객체에서의 멤버 팀 변경 질문
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]이 그림에거 테이블이 아닌 객체만을 이용해서 MemberA의 팀을 TeamA에서 TeamB로 변경하려면 자바에서 Member.setTeam("TeamB") 하고 TeamA의 리스트에서 MemberA를 삭제하고 TeamB에서 List의 MemberA를 추가해주어야 하는게 맞죠??