JPA 18

16장 트랜잭션과 락, 2차 캐시

👣 개요 해당 게시글은 JPA에서의 '트랜잭션과 락'과 '2차 캐시'에 대해 서술할 계획이다. JPA는 대부분의 DB는 READ COMMITTED 수준의 격리 수준을 요구한다. 이것은 성능 상 큰 이점을 줄 수 있어도 정확도 면에서는 손해를 볼 수 있다. JPA는 부분적으로 해당 격리 수준 이상의 격리 수준을 제공할 수 있다. Lock이 그 역할을 수행하고 이것을 심도있게 살펴본다. JPA는 영속성 컨텍스트를 이용해 요청 범위 내에서 같은 엔티티를 DB 2번 이상 호출하지 않도록 1차 캐시를 제공한다. 해당 캐시 덕분에 성능이 크게 늘어났지만 안타깝게도 '요청과 응답 사이'의 캐시를 도와주는 것이지 'Web App 차원'에서의 캐시를 제공하는 것은 아니기에 이전 요청을 위해 DB에서 조회했던 엔티티를 이..

JPA 2023.09.12

15장 고급 주제와 성능 최적화

👣 개요 해당 게시글은 JPA에서의 예외 처리, 엔티티 비교 시 주의사항, 성능 최적화에 대한 주제로 작성되었다. 👣 예외 처리 순수 JPA 단계에서의 예외 1. 트랜잭션 롤백을 발생시키는 예외 해당 예외는 심각한 예외이므로 강제 롤백된다. 2. 트랜잭션 롤백을 발생시키지 않는 예외 그다지 심각하지 않는 예외이므로 개발자 선택에 의해 커밋하던지 롤백한다. 예를 들어, 단일 조회를 했는데 조회된 내용이 하나도 없으면 발생하는 예외 같은 것을 의미한다. Spring Framework에서의 JPA 예외 변환 아래 Effective Java의 내용에 따르면 저수준의 라이브러리[Hibernate]에서 발생한 예외를 고수준의 라이브러리[Spring Data JPA]에서 그대로 노출되면 오류의 원인을 파악하기 어려워..

JPA 2023.09.09

14장 컬렉션과 부가 기능

👣 개요 해당 게시글에서는 JPA에서의 컬렉션, @Converter, 리스너, 엔티티 그래프에 대해서 배울 것이다. 1. JPA에서의 컬렉션 지연 로딩을 도와주는 컬렉션을 사용할 때, 의도하지 않은 시점에서의 지연 로딩을 알아야 한다. 2. @Converter 자바에서의 데이터값과 DB에서의 데이터값을 인코더와 디코더를 이용해서 쉽게 변환해주는 장치 3. 리스너 엔티티 상태변화에 따른 리스너를 제공하고 있다. 이에 따라 상태변화 시, 로깅을 하거나 특수한 업무를 자동으로 처리할 수 있다. 4. 엔티티 그래프 연관 관계의 엔티티를 한 번에 가져오는 형태를 취해서 N+1문제를 일으키지 않는 장치. JPQL의 fetch join과 같이 엔티티를 가져오지만 기존의 em.find() 메서드로도 호출할 수 있다. ..

JPA 2023.09.08

13장 웹 애플리케이션과 영속성 관리

👣 개요 해당 게시글은 Spring Framework로 구성된 웹 App에서의 영속성 관리 방법에 대한 글이다. Spring은 3 계층으로 웹 App을 관리하고 있고 각 계층에서의 올바른 JPA 영속성 관리 방법에 대해 이해하는 것은 매우 중요하다. 만약 영속성 컨텍스트의 생존 범위를 적절하지 못하게 설정한다면 원치하는 곳에서 Update 쿼리가 호출될 수도 있으며 지연 로딩에 의해 N+1 문제를 겪을 수도 있다. 👣 Spring Framework에서의 영속성 컨텍스트 스프링 컨테이너에서의 기본 영속성 컨텍스트의 생존 범위는 Service ~ Repository 이다. 동시에 트랜잭션의 범위 또한 Service ~ Repository 이다. 이는 Service 이외의 장소, 즉 Controller, Vi..

JPA 2023.09.07

12장 Spring Data JPA

👣 개요 실제로 Spring Boot에서 JPA를 사용할 때는 직접 메서드를 구현할 필요가 없다. Spring Data JPA를 이용하면 이미 많이 정형화된 Id를 이용한 단일 조회, 전체 조회, 생성, 삭제 등등 영속성 컨텍스트를 이용하는 메서드는 구현이 된 상태로 사용 가능하다. 어째서 JpaRepository를 상속받은 Repository를 정의하는 것만으로도 위와 같은 혜택을 누릴 수 있는지와 QueryDSL과 같은 기술과 접목시키는 방법 등을 해당 게시물에 기록할 예정이다. 👣 환경 설정 Spring Boot의 Gradle에 다음과 같은 설정이면 Spring Data JPA를 사용할 수 있다. dependencies { ... // JPA implementation 'org.springframe..

JPA 2023.09.06

영속성 컨텍스트 vs JPQL

👣 개요 JPQL은 영속성 컨텍스트에서 미리 조회하고 DB에 쿼리를 보내지 않고 DB에 쿼리를 먼저 보낸 후에 영속성 컨텍스트를 재정비한다. JPQL의 경우, 영속성 컨텍스트를 활용하지 않기 때문에 비교적 성능이 떨어질 수 있기 때문에 되도록 JPQL보다 find()와 같은 메서드를 사용하는 것이 좋다. 하지만, 통계 쿼리와 같은 복잡한 쿼리를 보내는 것에 영속성 컨텍스트를 활용하기란 어려움이 많기에 JPQL을 사용할 수 밖에 없다. 👣 플러시 모드와 최적화 원래 JPQL을 실행하면 Flush Mode가 FlushModeType.AUTO로 되어 있기 때문에 영속성 컨텍스트와 DB 사이의 동기화를 유지할 수 있다. FlushModeType.AUTO란, JPQL 쿼리를 DB로 보내고 결과를 받아올 때마다 영..

JPA 2023.09.06

QueryDSL

👣 개요 QueryDSL은 JPQL 언어를 그대로 작성함으로서 일어나는 단점을 커버하기 위해 생긴 기술이다. 해당 기술을 통해 런타임이 아닌 컴파일 단계에서 오류를 미리 잡아낼 수 있다는 특징이 있고 동적으로 쿼리를 작성할 수 있다는 장점이 있다. 👣 의존성 추가 Gradle 기준으로 QueryDSL의 의존성 추가하는 방법이다. dependencies { ... // JPA implementation 'org.springframework.boot:spring-boot-starter-data-jpa' // Querydsl 추가 implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta' annotationProcessor "com.querydsl:querydsl-a..

JPA 2023.09.06

10장 객체지향 쿼리 언어

👣 개요 여태까지의 JPA로는 제한적인 쿼리만 수행할 수 있었다. 때문에 복잡한 검색 조건을 사용하기 위해 다양한 쿼리 기술을 지원한다. JPQL, Criteria, QueryDSL 등등이 이것에 속한다. 👣 JPQL JPQL은 SQL과 달리 테이블 중심적 언어가 아니라 객체 지향적 언어다. SQL을 추상화해서 특정 벤더에 의존적이지 않아서 이식성이 좋다. 기본 문법 1. 대소문자 구분 2. 엔티티 이름 - Table 이름을 기입하는 것이 아닌 @Entity(name = "XXX")의 이름 속성을 사용한다. 3. 별칭 필수 - 'Member AS m' 과 같이 별칭을 꼭 사용해야 함. TypeQuery 클래스 쿼리 내용을 담고 있는 클래스로서 특정 메서드를 호출하면 DB에 쿼리에서 필요한 정보를 가지고 ..

JPA 2023.09.04

9장 값 타입

👣 개요 JPA가 인식하는 데이터 타입은 다음과 같이 3분류로 나눌 수 있다. 1. 기본값 타입 - 자바 기본 타입(Ex. int, Integer, double) 2. 임베디드 타입 - 복합 값 타입 3. 컬렉션 값 타입 이 중 1번은 이미 알고 있는 내용이기에 2번, 3번에 대해서만 서술한다. 👣 임베디드 타입 임베디드 타입은 DB에는 반영되지 않지만, OOP에서 좀 더 OOP 스럽게 코드를 구성하기 위해 사용하는 도구다. 예를 들어, 집 주소를 표현하는 필드가 도, 시, 동이라는 3개의 필드가 있을 때, 응집성을 높이기 위해 3개의 필드를 위치라는 클래스에 담고 위치 클래스 타입의 필드 1개로 치환하는 것이다. 변경 전 코드 @Entity public class Member { @Id private ..

JPA 2023.09.03

8장 프록시와 연관관계 관리

👣 개요 해당 게시물은 프록시를 이용해서 객체의 그래프 탐색에서 지연 로딩을 하는 방법에 대해 서술할 것이다. 👣 프록시 연관된 엔티티를 조회하는 방법은 2가지가 있다. 즉시 로딩 : 원래 엔티티를 조회할 때, DB에서 같이 불러오는 방법 지연 로딩 : 원래 엔티티는 엔티티대로 조회하고 연관된 엔티티를 호출할 때, 그때서야 DB에서 추가적으로 로드하는 방법 지연로딩을 실현시키기 위해 연관된 엔티티를 담는 필드에 실제 엔티티를 대입하는 것이 아니라 가짜 객체를 담고 해당 객체를 호출할 때, DB에서 조회하도록 설정한다. 이것을 프록시 객체라고 한다. // 실제 객체 호출 Member member = em.find(Member.class, 1L); // Proxy 객체 호출 Member member = em..

JPA 2023.08.31