반응형
반응형
Introduction N+1 문제는 JPA를 통해 서비스를 개발하다보면 마주칠 수 밖에 없는 문제입니다. 왜 이런 문제가 발생하고, 해결책은 무엇인지를 한 번 정리를 해놓으면 좋을 것 같아서 글을 쓰게 되었습니다. (예제는 SpringBoot + Spring Data Jpa 으로 환경을 구성 했습니다. 제일 대중적인 조합으로 문제를 다뤄야 이해하기 쉽다고 생각 했습니다.) N+1 문제 그래서 N+1 문제가 뭔데..? '데이터 조회 쿼리를 1개 요청할 경우 N개의 쿼리가 추가적으로 발생하는 문제' 이 문제는 MyBatis 처럼 직접 쿼리문을 생성하는 것이 아니라, 쿼리가 자동화된 JPA를 사용하게되면 겪을 수 밖에 없는 문제였지 않나 싶습니다. 결국 객체를 대상으로 조회하는 것이기 직접 조회하는 것과 ..
문제 Spring Data Jpa 에서 제공하는 deleteById 메소드를 사용해서 데이터를 삭제 했을 경우에 삭제 쿼리 하나만 실행되길 바랬는데. 삭제 쿼리가 실행되기 전에 삭제할 데이터를 찾는 조회 쿼리가 선행 되는 문제가 발생했다. 해결 @Override @Transactional @SuppressWarnings("unchecked") public void delete(T entity) { Assert.notNull(entity, "Entity must not be null!"); if (entityInformation.isNew(entity)) { return; } Class type = ProxyUtils.getUserClass(entity); T existing = (T) em.find(t..
문제 특정 데이터를 관리할 때. 두 가지 방식으로 PK 를 관리한다. 1. auto increase 되는 숫자를 PK 로 사용한다. 2. loginId, 주민번호, 식별 코드 등등 중복되지 않는 유일한 값을 PK 로 사용한다. 두 번째 방식으로 save() 로 새롭게 데이터를 저장할 경우 실행되는 쿼리는 insert 만 실행되길 기대하지만, 데이터를 조회하는 select 가 저장 할 때마다 계속 실행되는 문제가 생겼다. 해결 @Transactional @Override public S save(S entity) { Assert.notNull(entity, "Entity must not be null."); if (entityInformation.isNew(entity)) { em.persist(ent..
문제 프로젝트를 진행하는 중에 엔티티 저장하는 과정들을 try {} 로 감싼 후 에러가 발생하면 다른 특별한 조치 프로세스를 취해야 했다. 에러가 발생 했을 경우에 의도한대로 동작하지 않고, 해당 에러가 발생했다. 'null id in entry (don't flush the Session after an exception occurs)' 저장을 시도 했던 엔티티가 저장 하는 과정에서 에러가 발생 했고, 저장에 실패한 엔티티가 id 가 null 인 채로 준영속상태로 세션에 남아있는다. 그리고 마지막에 엔티티매니저가 Flush 되는 순간에 준영속상태로 남아있는 엔티티를 다시 저장을 시도할 때 id 가 null 이기 때문에 발생하는 에러다. 해결 hibernate 는 save() 에 실패 했다고 해서 ..
Introduction 보통 데이터를 정렬하고 싶을때 SQL 의 OrderBy를 사용하거나 프론트 테이블이 받은 행의 데이터를 원하는 기준으로 정렬한다. 보통의 웹사이트의 게시글들은 최신이 위로 오거나, 특정 테이블 헤더를 눌렀을 경우 그 데이터를 기준으로 정렬을 한다던지 말이다. '만약 페이지네이션이 걸려 있는 페이지에서 '제목'이라는 헤더를 눌렀을 경우 데이터는 어떻게 정렬되어야 할까?' 기존의 조회된 첫 번째 페이지의 데이터만 제목을 기준으로 정렬이 되면 될까 ? 아니면 모든 데이터를 기준으로 제목이 정렬되어야 할까 ? 물론 사람마다 원하는 바가 다르겠지만, 만약 후자라면 프론트 테이블에서 지원하는 정렬로는 해결할 수가 없기 때문에 결국 다시 서버로 요청을 해야한다. 그렇기 때문에 특정 정렬 조건..
Introduction 예전에 QueryDSL 를 통해 데이터를 조회할 때 바로 DTO 객체로 응답 받는 방법을 포스트(https://mokggang.tistory.com/68) 했었는데. 자식 객체 기준에서의 부모 객체를 조회하는(Object in Object) 것 말고, 부모 객체 기준으로 자식객체를 조회하는(ObjectList in Object) 데이터가 필요한 경우 '일대다 관계의 부모와 자식 엔티티를 Join 으로 모두 조회 할 경우에도 DTO 객체로 응답 받아서 사용할 순 없을까 ?' jpaQueryFactory. select( team.id, team.name )). from(team). join(team.memberList, member) fetch(); 위와 같이 TeamDTO 객체 ..