JPA
- JPA 선호하는 패턴
@Column(nullable = false)
vs@NotNull
→ 둘 다 테이블 생성시 not null 옵션을 추가해준다
@NotNull의 경우 실제 객체에 null 이 들어가는 경우에도 오류를 반환하므로 더 엄격하다
현업에서는 전자를 더 선호하는 듯 했다- JPA entity equals - 참고주소1, 참고주소2
- JPA의 즉시 로딩과 지연 로딩(p.296)
- @ManyToOne, @OneToMany : 즉시 로딩(FetchType.EAGER)
- @OneToMany, @ManyToMany : 지연 로딩(FetchType.LAZY)
- → 최대한 모든 연관관계에 지연 로딩을 사용하는 것을 추천!(출처는 영한님 책)
- JPA의 영속성 전이(p.307)
- 특정 엔티티를 영속 상태로 만들 때 연관된 엔티티도 함께 영속 상태로 만들고 싶으면 영속성 전이 기능을 사용
- 주로 mappedBy 속성이 지정된 객체에 cascade = CascadeType.PERSIST 추가
- 이러나 저러나
@ManyToOne
단방향을 최선으로! - 엔티티의 기본 생성자(빈 생성자)를 protected로 선언하는 이유? private은 불가능한지?
- 우선 Spring Data JPA와 관련하여 조회한 데이터를 setter나 new 연산자를 사용하지 않고도 객체를 생성한다는 것부터 시작해보자
- 이는 Spring Data JPA가 자체적으로 기본 생성자로 객체를 생성한 후 DB 값을 자바 Reflection API를 사용하여 값을 매핑하기 때문이다
- 자바 Reflection API은 구체적인 클래스 타입을 알지 못해도 클래스의 메소드나, 타입, 변수들에 접근할 수 있도록 해준다
- 여기서 또한 알아야 하는 부분은 지연 로딩과 프록시 인데,
- 지연로딩으로 인해 프록시 객체를 사용하는 경우 원본 엔티티를 상속한 프록시 객체를 생성하고 이후 실제 사용 시점에 실제 엔티티 정보를 조회하여 프록시 엔티티가 원본 엔티티를 참조하도록 한다.
- 즉, 상속받은 클래스(프록시 엔티티)에서 상속 대상 클래스(원본 엔티티) 호출이 필요하기 때문에 결과적으로 기본 생성자를 private 이 아닌 protected(public도 가능)로 선언해야 한다.
- 정리해보면, Spring Data JPA가 자바 Refelection API 를 사용하기 때문에 기본 생성자가 필요한데, 프록시 객체의 경우 상속 받는 대상 객체로의 참조가 필요하기 때문에 private으로는 선언이 불가능하다!
미션 하면서 고민한 점
- findById 처리 - Optional<Answer> vs orElseThrow
→ 정답은 없다 그때 그때 적절하게 처리하자 - 연관 관계 매핑 값 처리
- 기존 long type을 객체로 변경 → getter 처리는? → 객체를 리턴합시다
- 다대일 양방향 연관관계 설정하기
- @ManyToOne 과 함께 지연로딩 속성 추가(FetchType.LAZY)
- @OneToMany 에 mappedBy로 대상 매개변수명 추가 + 영속성 전이 속성 추가(cascade = CascadeType.PERSIST)
- id 값 자동 부여를 위한 생성자에서 id 호출 삭제 - Test에서 전부 3L 넣고 있었음→ 그보다도 cascade는 동시에 객체 두개를 다루는 개념인데, DELELE 외에는 동시에 작업이 될 일이 많지 않기 때문에 repository.save가 더 적절하다! (예를 들면 질문에 대한 답변은 동시에 달리지 않음!)
→ 찾아본 결과 영속성 ‘전이’ 라는 것은 결국 옵션을 준 객체가 대상 객체에 영속성 전이를 하는 개념이기 때문에 실질적으로는 @ManyToOne에 넣는 것이 맞는데, 저 cascade 자체를 지양하기 때문에 결론적으로는 cascade 하기보다는 귀찮더라도 repository.save 로직을 호출하자
미션과 관련된 알쓸지식
반응형