JPA
2. 공통 인터페이스 기능
순수 JPA 기반 리포지토리 만들기 우선 순수한 JPA기반 리포지토리를 만들어 보자 기본 CRUD 1. Create(저장) public Member save(Member member) { em.persist(member); return member; } 2. Update(변경 → 변경감지 사용) JPA에서 수정은 변경감지 기능을 사용하면 된다. 트랜잭션 안에서 엔티티를 조회한 다음에 데이터를 변경하면, 트랜잭션 종료 시점에 변경감지 기능이 작동 해서 변경된 엔티티를 감지하고 UPDATE SQL을 실행한다. 3. Delete(삭제) public void delete(Member member) { em.remove(member); } 4. Read(조회) public Member find(Long id) {..
1. 프로젝트 환경설정 & 예제 도메인 모델
프로젝트 생성 Spring boot IntelliJ-ultimate 버전이 아니라면 스프링 부트 스타터를 이용 (https://start.spring.io/) 사용 기능(라이브러리); web, jpa, h2, lombk SpringBootVersion: 2.7.15 groupId: study artifactId: data-jpa Gradle config code plugins { id 'java' id 'org.springframework.boot' version '2.7.15' id 'io.spring.dependency-management' version '1.0.15.RELEASE' } group = 'study' version = '0.0.1-SNAPSHOT' java { sourceCompati..
OSIV와 성능 최적화
OSIV와 성능 최적화 Open Session In VIew: 하이버네이트 Open EntityManager In View: JPA (관례상 OSIV라 한다.) 하이버네이트에선 EntityManeger를 Session이라고 칭한다. JPA는 하이버네이트 이후에 표준화를 위해 생겼기 때문에 이런 용어 차이가 발생했다. OSIV ON spring.jpa.open-in-view : true 기본값 → 이 기본값을 뿌리면서 애플리케이션 시작 시점에 warnning 로그를 남기는 것은 이유가 있다. 기본적으로 JPA 는 언제 DB 커넥션을 가져오고 반환할까? JPA 즉, 영속성 컨텍스트는 DB 커넥션을 내부적으로 사용해야 지연 로딩 같은 작업이 가능하다. 이 말은 곧 영속성 컨텍스트와 DB 커넥션은 밀접하게 매칭..
API 개발 고급 - 컬렉션 조회 최적화
주문내역에서 추가로 주문한 상품 정보를 추가로 조회하자. Order기준으로 컬렉션인 OrderItem 와 Item 이 필요하다. 앞선 예제에서는 xxxToOne(OneToOne, ManyToOne)관계만 있었다. 이번에는 컬렉션인 일대다 관계(OneToMany)를 조회하고 최적화 하는 방법을 알아보자. 주문 조회 V1: 엔티티 직접 노출 package jpabook.jpashop.api; import java.util.List; import jpabook.jpashop.domain.Order; import jpabook.jpashop.domain.OrderItem; import jpabook.jpashop.repository.OrderRepository; import jpabook.jpashop.repo..
API 개발 고급 - 지연 로딩과 조회 성능 최적화
사전 준비 - 조회용 샘플 데이터 입력 jpabook::jpashop::InitDb /** * 총 주문 2개 * userA * JPA1 BOOK * JPA2 BOOK * userB * SPRING1 BOOK * SPRING2 BOOK */ @Component @RequiredArgsConstructor public class InitDb { private final InitService initService; @PostConstruct public void init() { initService.dbInit1(); initService.dbInit2(); } @Component @Transactional @RequiredArgsConstructor static class InitService { priva..
API 개발 기본
회원 등록 API ※ 참고 패키지 분리 일반적으로 템플릿 엔진을 사용하여 랜더링하는 Controller와 API 스타일의 Controller를 분리한다. 왜냐하면 공통으로 예외처리를 할 때 패키지나 구성단위를 기준으로 공통 처리를 하는데 api와 화면의 공통 처리 요소가 다르다. 예를 들어 화면의 경우 에러가 발생하면 공통 에러 html 페이지를 반환하고 API의 경우 공통 에러 JSON을 반환한다. 회원 등록 API - V1 package jpabook.jpashop.api; import javax.validation.Valid; import jpabook.jpashop.domain.Member; import jpabook.jpashop.service.MemberService; import lombok..
12. 객체지향 쿼리 언어2 - 중급 문법
경로 표현식 .(점)을 찍어 객체 그래프를 탐색하는 것 select m.username -> 상태 필드 from Member m join m.team t -> 단일 값 연관 필드 join m.orders o -> 컬렉션 값 연관 필드 where t.name ='팀A' 경로 표현식 용어 정리 상태 필드(state field): 단순히 값을 저장하기 위한 필드(ex: m.usernmae) 연관 필드(association field): 연관관계를 위한 필드 단일 값 연관 필드 @ManyToOne, @OneToOne: 대상이 엔티티(ex: m.team) 컬렉션 값 연관 필드 @OneToMany, @ManyToMany: 대상이 컬렉션(ex m.orders) (중요) 경로 표현식 특징 상태 필드(state fiel..
10. 값 타입 2 (값 타입 비교, 컬렉션)
값 타입의 비교 값 타입은 인스턴스가 달라도 그 안에 값이 같으면 같은 것으로 봐야 한다. // primitive type 비교 int a = 10; int b = 10; System.out.println(a == b);//true // 임베디드 타입(인스턴스) 비교 Address a = new Address("서울", "AAA", 1000); Address b = new Address("서울", "AAA", 1000); System.out.println(a == b);//false 어째서 임베디드 타입의 ==비교는 false가 뜨는것인가? 당연하다. 인스턴스가 다르니 다른 객체이기 때문이다. 그럼 어떻게 해야할까? 동일성(identity) 비교: 인스턴스의 참조 값을 비교, == 사용 동등성(equiv..
9. 값 타입 1 (기본값 타입, 임베디드 타입, 값 타입과 불변 객체)
기본값 타입 JPA의 데이터 타입 분류 최상위 레벨로 보면 JPA는 데이터 타입을 두 가지로 분류한다. 엔티티 타입 @Entity로 정의하는 객체 데이터가 변해도 식별자로 지속해서 추적 가능 ⇒ 엔티티 내부의 모든 값들을 바꿔도 식별자만 유지되면 추적이 가능하다는 의미 Ex: 회원 엔티티의 키나 나이 값을 변경해도 식별자로 인식 가능 예를 들어 식별자가 100번일 경우 키나 나이 값이 바껴도 식별자는 그대로 100번이라는 것 값 타입 int, Integer, String처럼 단순히 값으로 사용하는 자바 기본 타입이나 객체 식별자가 없고 값만 있으므로 변경시 추적 불가 ex. 숫자 100을 200으로 변경하면 완전히 다른 값으로 대체 ex. 게시판의 String 컨텐츠가 바뀌면 추적이 불가능. 단, Boa..