spring/JPA 11

[JPA] OSIV와 성능 최적화 (Open Session in View란?)

OSIV(Open Session In View) 란?OSIV란 영속성 컨텍스트를 View 영역까지 열어두는 기능이다.즉, View 레이어에서도 지연로딩과 같은 영속성 컨텍스트의 특징을 사용할 수 있다. Spring boot에서 OSIV는 default가 true기 때문에 따로 설정을 바꿔주지 않는 한 항상 실행된다. 데이터베이스 커넥션JPA는 언제 데이터베이스 커넥션을 가져오고 언제 커넥션을 반환할까? JPA에서 영속성 컨텍스트를 사용하기 위해선 당연히 데이터베이스 커넥션을 사용해야한다. 기본적으로 데이터베이스 트랜잭션을 시작할 때 영속성 컨텍스트가 데이터베이스 커넥션을 가져온다.다음과 같이 보통 Service 단에서 트랜잭션이 시작하니 위의 트랜잭션 코드가 실행될 때 데이터베이스 커넥션이 만들어지는 것..

spring/JPA 2024.08.27

[JPA] API 개발과 성능 최적화 3 (페이징과 한계 돌파)

컬렉션을 페치 조인하면 페이징이 불가능하다. 오더와 아이템이 일대다의 관계고, 현재 페치조인을 한 상태라고 생각해보자 우리는 페이징을한다면 오더를 기준으로 페이징을 해야한다. 그러나 데이터는 다(Many), 즉 Item을 기준으로 row가 생성된 상태다.  그러니 이 상황에서 페이징을 하면 오더가 기준이 아닌 Item이 기준이 된다. 이 경우 하이버네이트는 order를 기준으로 페이징을 하기 위해 경고 로그를 남기고 모든 DB 데이터를 읽어 메모리에서 페이징을 시도한다. 그러면 페치 조인 상황에서 페이징을 하려면 어떻게 해야할까? 해결 방법먼저 ToOne 관계의 모든 엔티티를 페치조인 한다. (ToOne 관계는 row 수를 증가시키지 않기 때문)컬렉션은 지연 로딩으로 조회한다.지연 로딩 성능 최적화를 위..

spring/JPA 2024.08.11

[JPA] API 개발과 성능 최적화 2 (컬렉션 조회 시 성능 최적화)

컬렉션 조회 최적화엔티티 직접 노출@GetMapping("/api/v1/orders")public List orderV1(){ List all = orderRepository.findAllByString(new OrderSearch()); reuturn all;}현재 하이버네이트 버전 5를 bean으로 등록 시켜준 상황이어서 영속성 컨텍스트에 전부 객체가 들어와 있는 상태다. 추가적으로 양방향 관계는 다 @JsonIgnore을 다 만들어주어야 한다. 이 방법은 역시 저번에도 설명했던 것 처럼 엔티티를 직접 노출하기에 단점이 굉장히 많아,사용하면 안 된다. 엔티티를 Dto로 변환@GetMapping("/api/v2/orders")public List orderV2(){ List orders = ord..

spring/JPA 2024.08.10

[JPA] API 개발과 성능 최적화 1 (지연 로딩과 조회 성능 최적화)

API를 개발하는 여러가지 방법들과 성능을 최적화 시키는 법을 공부해 보겠다. 엔티티 직접 노출 방식 API @GetMapping("/api/v1/simple-orders") public List ordersV1(){ List all = orderRepository.findAllByString(new OrderSearch()); return all; }우선 위와 같이 엔티티를 그대로 노출하는 api를 하나 만들어 보았다. public class Order { @Id @GeneratedValue @Column(name = "order_id") private Long id; @ManyToOne(fetch = FetchType.LAZY) @Jo..

spring/JPA 2024.08.08

[JPA] 객체 지향 쿼리 언어 JPQL 7 (엔티티 직접 사용, 네임드 쿼리, 벌크 연산)

엔티티 직접 사용 - 기본 키 값JPQL에서 엔티티를 직접 사용하면 SQL에서 해당 엔티티의 기본 키 값을 사용한다.[JPQL]select count(m.id) from Member m // 엔티티의 아이디를 사용select count(m) from Member m //엔티티를 직접 사용[SQL]select count(m.id) as cnt from Member m두 JPQL 다 동일한 SQL이 실행된다.엔티티를 파라미터로 사용해도 똑같이 엔티티는 기본 키 값으로 처리 된다. 엔티티가 데이터베이스에 전달되면 데이터베이스에서는 엔티티를 당연히 기본 식별자로 구분하므로,엔티티가 기본 키 값으로 처리되는 것이다. Named 쿼리 - 정적 쿼리미리 정의해서 이름을 부여해두고 사용하는 JPQL정적 쿼리어노테이션,..

spring/JPA 2024.08.07

[JPA] 객체 지향 쿼리 언어 JPQL 6 (fetch join의 한계, 다형성 쿼리)

페치 조인의 한계페치 조인 대상에는 별칭을 줄 수 없다하이버네이트는 가능하나 가급적 사용하지 말 것별칭을 주고 select t from Team t join fetch t.members m where m.age > 10;과 같이 조회하게 되면 멤버의 전체를 가져오는 것이 아닌 멤버의 일부만 가져오게 된다.그러나 JPA는 fetch를 사용하면 모든 객체를 가져오는 것을 기본으로 설계가 돼있기 때문에어디서 예상치 못 한 오류가 발생할지 알 수 없다.둘 이상의 컬렉션은 페치 조인 할 수 없다ONE to MANY 상황에서 페치 조인하고 거기에 또 컬렉션을 페치 조인 하는 상황을 의미한다.ONE to MANY에서도 데이터가 뻥튀기가 되는데 거기에 컬렉션을 한 번 더 페치 조인 시키면데이터가 얼마나 뻥튀기 될 지 ..

spring/JPA 2024.08.06

[JPA] 객체 지향 쿼리 언어 JPQL 5 (경로 표현식, fetch join)

경로 표현식.(점)을 찍어 객체 그래프를 탐색하는 것이다. select m.username -> 상태필드로 객체를 탐색한 경우from Member m   join m.team t -> 단일 값 연관 필드 (여기서 team은 엔티티기 때문에 단일 값을 탐색한 것이다.)   join m.orders o -> 컬렉션 값 연관 필드 (여기서 orders는 컬렉션이어서 컬렉션을 탐색한 것이다.)where t.name = '팀A' .을 통해 상태 필드로 가냐, 단일 값 연과 필드로 가냐, 컬렉션 값 연관 필드로 가냐에 따라서내부적으로 동작하는 방식이 다 달라진다.  용어 정리상태 필드: 단순히 값을 저장하기 위한 필드다 (ex: m.username)연관 필드: 연관 관계를 위한 필드다단일 값 연관 필드: @Many..

spring/JPA 2024.08.04

[JPA] 객체 지향 쿼리 언어 JPQL 4(기본 문법 - 조인, 서브쿼리, 조건식 , 기본 함수)

조인내부 조인:select m from Member m [inner] join m.team t외부 조인:select m from Member m left [outer] join m.team t세타 조인:select count(m) from Member m, Team t where m.username = t.name[]는 생략이 가능하다. 조인 - ON 절조인 대상 필터링이 가능하다.예) 회원과 팀을 조인하면서, 팀 이름이 A인 팀만 조인JPQL: select m, t from Member m left join m.team t on t.name = 'A'SQL: select m.*,t.* from Member M left join Team t on m.team_id = t.id and t.name = 'A..

spring/JPA 2024.08.03

[JPA] 객체 지향 쿼리 언어 JPQL 3 (기본 문법 - 프로젝션, 페이징)

프로젝션프로젝션이란 select 절에 조회할 대상을 지정하는 것이다. 프로젝션 대상: 엔티티, 임베디드 타입, 스칼라 타입 모든 것이 가능하다.(SQL 은 기본 데이터 타입만 가능함) select m from Member m -> 엔티티 프로젝션 select m.team from Member m -> 엔티티 프로젝션 (멤버 엔티티와 연관된 Team 테이블을 가져옴) 더보기select m.team from Member m 은 SQL에서 member테이블과 team 테이블을 조인 시킨 후에 결과를 가져온다. 위의 jpql만 보면 조인 쿼리가 나가는 것인지 아닌지 바로 알아차리기 힘들기 때문에, 유지 보수성을 위해 select m.team from Member m 대신 select T from Member m..

spring/JPA 2024.07.31

[JPA] 객체 지향 쿼리 언어 JPQL 2 (기본 문법)

JPQL 문법jpql 문법은 sql 문법과 동일하다.  엔티티와 속성은 대소문자를 구분한다. EX) select m from Member as m where m.age > 18 ) 여기서 member와 age의 대소문자가 틀리다면 쿼리가 실패한다.jpql 키워드는 대소문자를 구분하지 않는다. (select, from ,WHERE 등등 ,,)테이블의 이름이 아닌 엔티티의 이름을 사용한다.별칭 (m)은 필수이며, as는 생략 가능하다.집합과 정렬위의 함수들 및 Group By, HAVING, ORDERBY 모두 지원한다. TypeQuery, QueryTypeQuery: 반환 타입이 명확할 때 사용한다.TypedQuery query = em.createQuery ("select m from Member m",..

spring/JPA 2024.07.29