JPA5 일대다 페이지네이션 최적화하기 일대다 컬렉션에 대한 페치 조인과 페이지네이션을 함께 사용하는 경우 다음과 같은 로그를 확인할 수 있습니다. 일대다 조인을 수행하는 경우 다 쪽의 데이터만큼 결과 row가 증가하기 때문에 DB에서 페이지네이션을 수행할 수 없습니다. 하이버네이트는 메모리 상에서 페이징을 시도하게 되면서 applying in memory라는 경고 로그를 남깁니다. 이러한 페이지네이션을 개선하기 위해서는 다음 2가지 방법을 사용할 수 있습니다. BatchSize 프로젝션 + IN절 쿼리 -> 애플리케이션 상에서 조인 수행 BatchSize BatchSize를 사용하기 위해서는 hibernate.default_batch_size를 이용해 글로벌로 설정하거나 @BatchSize를 일대다 컬렉션에 추가하여 개별적으로 설정할 수 있.. 2023. 12. 13. 엔티티 매니저와 영속성 컨텍스트 1. 엔티티 매니저란? 엔티티 매니저는 엔티티를 저장, 수정, 삭제, 조회 등 엔티티와 관련된 모든 일을 처리하는 관리자이다. 내부에 데이터소스를 유지하면서 데이터베이스와 통신한다. 개발자 입장에서 엔티티 매니저를 엔티티를 저장하는 가상의 데이터베이스로 생각하면 된다. 이때, 엔티티 매니저는 데이터베이스 커넥션과 밀접한 관계가 있으므로 스레드간에 공유하거나 재사용해서는 안 된다. 이러한 엔티티 매니저는 엔티티 매니저 팩토리에 의해서 생성된다. 엔티티 매니저 팩토리 엔티티 매니저 팩토리는 엔티티를 만들기 위한 공장이다. JPA 구현체에 따라 데이터베이스 커넥션 풀도 생성하므로 엔티티 매니저 팩토리를 생성하는데 많은 비용이 든다. 때문에 어플리케이션은 하나의 엔티티 매니저 팩토리를 공유해서 사용해야 한다. .. 2023. 7. 30. JdbcTemplate batchUpdate()를 이용한 Batch insert 프로젝트 진행 중 대량의 insert를 수행할 필요가 있었습니다. 시나리오는 아래와 같습니다. 1. ticket 이 만료되면 ticket_record 가 생성됩니다. ticket_record는 만료시간, 활성시간(단위: 초) 필드를 가집니다. 2. 하루가 종료되는 시점에 만료되지 않은 ticket 이 존재하면 일괄적으로 만료시켜야 합니다. 3. ticket 의 일괄 만료에 따라 ticket_record 의 일괄 생성이 필요합니다. JPA saveAll() @Test void saveAll() { //given List members = new ArrayList(); for(int i=0; i 2023. 4. 24. [querydsl] in절 동적 쿼리 작성 주의점(1=2) 프로젝트를 진행하며 querydsl로 동적 쿼리를 처리해주고 있다. 태그와 같은 기능을 위해서 여러개의 태그를 가진 게시글을 검색해주기 위한 in 절을 사용하고 있다. 이때 제대로 처리를 해주지 않아 문제가 발생했다. private BooleanExpression studyIdIn(List studyIds) { return studyIds != null ? postStudy.study.id.in(studyIds) : null; } 태그를 위한 검색 조건 중 studyIds라는 필드가 있는데 이것이 null 인 경우에는 위 메서드에 의해서 null 값이 반환되어 where 절에서 무시된다. 테스트시에도 항상 studyIds 필드에는 null을 지정하거나, id들을 지정해서 넣었기 때문에 문제가 발생하지 않.. 2023. 4. 3. JPA에서 네이티브 SQL 사용하기 프로젝트 진행 중 사용자가 생성한 유효한 티켓을 일괄적으로 만료시켜줄 필요가 있었다. 업데이트가 필요한 필드 중에 티켓의 생성 시각과 종료 시각의 유닉스 시간을 뺀 값을 기록하는 필드가 있었기 때문에 기존에 JPQL 만으로 해결하기에는 문제가 있었다. Spring Data JPA에서 네이티브 SQL을 사용하기 위해서는 기존의 @Query 애노테이션을 nativeQuery = true 로 설정해주기만 하면 된다. 이때 테이블의 컬럼명과 동일한 이름을 사용하는 것에 주의하여야 한다. @Modifying @Query(value = "update Ticket t" + " set t.ticket_status='END'," + " t.end_time=:endTime," + " t.active_time=:endTim.. 2023. 3. 6. 이전 1 다음