JPA 23

Spring Data JPA 공통 인터페이스

Spring Data JPA를 사용하게되면 인터페이스를 상속받는 것 만으로도 save, findById 와 같이 제공되는 메서드를 구현없이 사용할 수 있다. 어떻게 이것이 가능한 것일까? 주입받은 memberRepository 인스턴스를 직접 출력해보자. Spring Data JPA가 인터페이스를 보고 구현클래스를 만들어 프록시 객체를 만들어 넣어준 것이다. 따라서 우리는 인터페이스만 만들어 놓으면 구현체는 Spring Data JPA가 만들어 주입해준다. 또한 @Repository 애노테이션 생략이 가능하다. 컴포넌트 스캔을 스프링 데이터 JPA가 자동으로 처리한다. JPA 예외를 스프링 예외로 변환하는 과정도 자동으로 처리해준다.(원래는 @Repository가 하는 기능임) JpaRepository를..

스프링 데이터 JPA 맛보기

Repository 인터페이스를 만들고 JpaRepository를 상속받아 사용한다. 상속 관계를 다이어그램으로 살펴보면 위와 같고 JpaRepository를 상속받으므로써 이미 구현되어있는 save(), findAll() 등과 같은 필요한 거의 모든 메서드를 바로 사용할 수 있다. 스프링 데이터 JPA는 JpaRepository 라는 인터페이스를 제공하는데, 여기에 기본적인 CRUD 기능이 모두 제공된다. (일반적으로 상상할 수 있는 모든 기능이 다 포함되어 있다.) 하지만 interface이기 때문에 구현체가 필요한거 아니야?? 구현체도 스프링 데이터 JPA가 알아서 만들고 주입해준다. 위와 같은 메서드는 모두 필요없어진다. findByName은 공통할 수 없으므로 JpaRepository에서 제공하..

OSIV

OSIV = Open Session In View(하이버네이트) Open EntitiyManager In View(JPA) 하이버네이트에서의 Session이 JPA에서의 EntityManager이다.(관례상 OSIV라고 부름) OSIV ON(default) spring.jpa.open-in-view:true // 기본값 애플리케이션을 실행하면 스프링부트는 다음과 같은 warning 로그를 남긴다. WARN 25168 --- [ restartedMain] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during ..

API 개발 고급

1. 지연 로딩과 조회 성능 최적화 엔티티를 직접 노출 저장된 모든 order를 찾아 리스트에 담고 엔티티를 그대로 반환 Postman으로 요청을 전송해보자. 먼저 앞서 공부한 것과 같이 엔티티를 그대로 노출하는 것은 굉장히 좋지 않은 행위이다. 또한, 응답을 보면 무한 loop에 빠져 StackOverflow가 발생하는 것을 확인할 수 있다. 이는 Order와 Member가 현재 양방향 관계로 매핑되어 있기 때문에 양방향관계에 의한 순환 참조로 인해 무한 Loop가 발생하기 때문이다. 이를 어떻게 해결하여야 할까? 현재 주문을 조회하고 있기 때문에 반대쪽 Member, OrderItem, Delivery에서 Order로 오는 것을 @JsonIgnore을 통해 막아야한다. 즉, 양방향 연관관계가 걸리는 ..

API 개발 기본

엔티티를 파라미터로 받을 경우의 문제 컨트롤러 엔티티 검증을 위한 @NotEmpty같은 로직들이 엔티티에 추가된다. 엔티티를 위한 매우 다양한 API가 만들어지는데, 한 엔티티에 각각의 API를 위한 요구사항들을 담기는 어려움 가장 큰 문제는 엔티티가 변경되면 API 스펙 자체가 변한다. 만약 엔티티의 name필드가 username으로 변경된다면 API 스펙 자체가 변하기 때문에 큰 문제가 발생한다. API 요청 스펙에 맞춰 별도의 DTO클래스를 만들어 DTO 객체를 파라미터로 받아야한다. 절대 파라미터로 엔티티를 바로 받지 말자!! 엔티티를 API 스펙에 노출 X 이와 같이 따로 DTO 클래스를 만들어 파라미터로 받아야한다. 예제를 위해 setter를 사용했지만 실제는 사용 X 엔티티와 표현 계층을 위..

변경 감지와 병합(merge)

준영속 엔티티 영속성 컨텍스트가 더는 관리하는 않는 엔티티를 의미한다. DB에 한번 저장되어 식별자가 존재하는 엔티티. persist() 메서드를 통해 영속성 컨텍스트에 담겼을 때는 식별자가 존재되고, 객체만 생성되었을 때는 식별자가 존재하지 않는다. 따라서 식별자가 존재한다면 준영속 엔티티로 볼 수 있다. 준영속 엔티티를 수정하는 2가지 방법 1. 변경 감지 기능 == dirty checking 2. 병합 사용 == merge JPA가 관리하는 영속 엔티티는 변경 감지를 통해 어떤 것이 변경되었는지 JPA가 알고 있기 때문에 트랜잭션 COMMIT 시점에 바뀐 부분을 자동으로 UPDATE SQL문을 날려 바꿔준다. 변경 감지 기능 사용 Id를 기반으로 영속성 컨텍스트안의 영속성 엔티티를 가져온다. 이것을..

엔티티 설계 주의점

엔티티에는 가급적 Setter를 사용하지 말자 Setter가 모두 열려있으면 변경 포인트가 많아지고, 어디서 변경되었는지를 알아내기가 어려워진다. ==> 유지보수가 어렵다. ★모든 연관관계는 지연로딩으로 설정(FetchType.LAZY) ==> 중요!!!!!! 더보기 EAGER는 하나의 객체를 DB로부터 읽어올 때 참조 객체들의 데이터까지 전부 읽어오는 방식을 뜻한다. 반대로 LAZY 타입은 게을러서, 참조 객체들의 데이터들은 무시하고 해당 엔티티의 데이터만을 가져온다. EAGER은 예측이 어렵고, 어떤 SQL이 실행될지 추적하기 어렵다. JPQL을 실행할 때 N + 1 문제가 자주 발생 모든 연관관계는 LAZY(지연로딩)으로 설정해야함. 연관된 엔티티를 함께 DB에서 조회해야 하면, fetch join..

도메인 모델, 테이블 설계

회원 - 주문 = 1 : N 회원은 여러 상품을 주문할 수 있다. 주문 - 상품 = N : M 주문은 여러 상품을 선택할 수 있고, 상품은 여러 주문에 들어갈 수 있으므로 다대다 관계 하지만 RDB는 물론 엔티티에서도 다대다 관계는 거의 사용하지 않는다. 주문 상품이라는 중간 테이블을 만들어 1대다 + 다대1 관계를 통해 다대다 관계를 구현 상품 상품은 도서, 음반, 영화로 구분 상품이라는 공통 속성을 사용하므로 상속 구조 엔티티 회원(Member) 이름, 임베디드 타입인 주소(Address), 주문 리스트(orders) 더보기 2021.05.17 - [Java/JPA] - @Embedded, @Temporal @Embedded, @Temporal @Embedded (임베디드 타입) 임베디드 타입이란 새..

@Embedded, @Temporal

@Embedded (임베디드 타입) 임베디드 타입이란 새로운 타입을 사용자가 직접 정의하여 사용하는 것을 뜻한다. 이는 int, String처럼 값 타입이다. 임베디드 타입을 사용하지 않는 Member @Entity public class Member { @Id @GeneratedValue private Long id; private String name; @Temporal(TemporalType.DATE) Date startDate; @Temporal(TemporalType.DATE) Date endDate; private String city; private String zipcode; } 위와 같이 상세한 데이터를 모두 가지고 있는 것은 객체지향적이지 않고 효율적이지 못하다. 이를 근무 기간, 주소..

Java/JPA 2021.05.17
반응형