반응형
반응형
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 서비스 로직에서 특정 데이터를 업데이트, 즉 변경 하기 위해서 JPA 를 사용할 경우 일반적으로 DirtyChecking 을 통해 업데이트를 진행한다. 하지만 다수의 데이터를 일괄적으로 변경을 해야하는 경우에는 다수의 조회 및 업데이트 쿼리가 발생하기 때문에 성능적으로 좋지 않다. 그런 경우 JPQL 을 통해 업데이트 쿼리를 직접 작성하여 Bulk 업데이트를 진행하기도 하는데. Querydsl를 통해 문자열로 이루어진 JPQL 업데이트 쿼리의 Set 파라미터를 동적으로 업데이트를 진행할 수 있다. Bulk update 1.JPQL JPQL을 통한 기본적은 Bulk Update는 단순한 문자열 형태로 진행된다. 아래 코드는 Repository에서 나이와 유저아이디로 해당 유저들의 ..
Introduction 백엔드에서 일반적으로 서비스 로직을 구성할 때 매개변수와 전달인자로 DTO를 사용한다. 여러가지 이유가 있겠지만, 필자가 생각하는 기본적인 이유는 1. 데이터의 종류와 타입 등 클라이언트의 요구사항이 다르다. - 서비스에서 클라이언트의 요구사항에 맞는 데이터를 가공 및 추가하는 과정이 필요하고, 불필요한 데이터를 응답할 필요가 없다. 2. Entity 객체의 필드 값을 예상하기 힘들다. - Entity 객체는 특정조건에 따른 결과물일 수도 있기 때문에 특정 데이터에 관해 직관적이지 못하고, 코드 추적이 불가피하다. 3. Entity 객체의 데이터의 무결성 - 서비스 로직에서 전달인자와 매개변수로 Entity 객체를 사용하게 되면, 의도치 않게 Entity의 값이 변경될 경우 JPA..