JPA
-
JPA Repository 기본 postfix로 인한 순환참조 해결Spring Framework 2023. 7. 30. 19:40
1) 서론 요즈음 스프링 프레임워크를 사용한다면 Spring Data JPA는 기본적으로 사용하게 되는데요. ORM 프레임워크는 RDB의 테이블을 객체로서 나타내고 맵핑할 수 있게 합니다. 애플리케이션에서 테이블에 질의할 때 쿼리와 데이터 중심이 아닌 객체로서 바라보는 것이 가능해졌습니다. 객체지향적인 설계에 큰 도움을 주게 됩니다. 이외에도 메서드를 활용하여 자동완성 되는 쿼리를 손쉽게 사용할 수 있는데요. 하지만 JDBCTemplate 같은것을 활용하여 쿼리를 날리는 것에 비해 주의해야 할 점이 많이 생겼습니다. 영속성 컨텍스트를 이해하지 못하거나 트랜잭션의 관리가 잘 되지 않는다면 예상치 못한 문제들이 발생할 수도 있는데요. 이번에는 Repository를 정의하고, 이에 대한 순환참조가 발생한것을 ..
-
Querydsl cross join 개선 하기Spring Framework 2022. 6. 18. 19:48
1) 서론 회사에서 Spring Data JPA는 서버 개발의 공통 기술 스택입니다. 그리고 당연하게 where 절을 많이 사용하는데요. 이때 만난 문제점을 개선하고 이를 공유하고자 합니다. Querydsl 뿐만 아니라, Spring Data JPA를 사용해보셨다면 이미 알고 계신 내용일 수도 있는데요. 그런 분들은 이번 글은 skip 하셔도 좋을 것 같습니다. 2) Querydsl where절의 문제점 ORM 프레임워크 상 혹은 SQL 쿼리를 직접 사용할 때 where절은 숨 쉬듯 자연스럽게 사용됩니다. 하지만 이러한 where절이 문제점을 일으킬 것이라고는 생각하지 못했었는데요. 어떤 문제가 있을까요? @Table(name = "book", schema = "test") @Entity class B..
-
FK 없는 OneToOne 즉시 로딩 개선하기Spring Framework 2022. 6. 7. 00:08
1) 서론 이번 글에서는 업무 중 발견한 레거시 코드의 문제점을 개선한 것을 공유하고자 합니다. 다양한 로직에서 빈번히 조회되고 있던 엔티티가 있었는데요. 특별히 문제가 발생하지 않았기 때문에 실제로 발생하는 쿼리를 주의 깊게 보지 않았었습니다. 하지만 우연히 지나치게 많은 쿼리가 발생하고 있는 것을 발견했습니다. 최초의 설계 의도는 지연 로딩을 하고자 했던 것 같지만, 실제로는 즉시 로딩이 되고 있었습니다. N+1 문제가 발생하고 있었는데요. 적은 스펙의 IDC 환경에서 돌아가는 애플리케이션을 운영하는 입장에서 불필요한 쿼리 개선 하나하나가 소중한 상황입니다. 이러한 레거시 코드를 개선하고, 변경한 내용을 공유합니다. 2) DB schema 모든 테이블 구조 및 로직은 재현을 위해 임의로 만들었습니다..
-
JPA cascade 멈춰!Spring Framework 2022. 2. 2. 18:23
1) 서론 업무 중 수십 개의 테이블에 걸친 데이터를 한 번에 지워야 하는 API를 만들어야 했습니다. 처음에는 고작 CRUD인데, 금방 하겠지라는 마음을 가지고 시작했습니다. 이때 생각지도 못 한 어려움을 만났는데요. 하마터면 관련 없는 데이터까지 삭제할 뻔했습니다. 왜 이러한 일이 발생했는지 재현 후 기록합니다. 2) 전체 구조 2. 1) DB 스키마 User, Role, Post 테이블이 있습니다. User, Role을 연결시켜주는 User_Role 매핑 테이블이 존재합니다. 2. 2) Entity 글과 관련 없는 애노테이션들은 모두 생략했습니다. @Entity public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) p..
-
JPA N+1 문제를 해결해보자Spring Framework 2021. 8. 20. 17:41
1) N+1 문제란? ORM은 객체의 관계를 연결하는데요. 이를 활용하는 JPA는 엔티티 기준으로 쿼리를 사용하고, 엔티티에 연관된 모든 객체를 조회합니다. 모든 연관된 객체를 조회 하기에 문제가 발생합니다. N개의 결과를 얻기 위해 DB를 조회했는데, 추가적으로 쿼리가 발생하는 것입니다. 즉 얻고자 하는 결과에서 1개가 더 붙어서 조회가 되는 현상입니다. 마트에서 하는 1+1 행사라고 생각하시면 됩니다. "파를 샀더니, 마늘을 주네? 근데 난 마늘 안 먹는데... 이걸 굳이 왜..?" 얻고자 하는 결과 외에 추가로 결과를 얻는다는 것은, 추가 쿼리가 발생합니다. 그만큼 성능적으로 손해 볼 수밖에 없습니다. 2) 전체 구조 // 애노테이션들 생략 했습니다. public class Post { privat..
-
[JPA, Redis]페이지별 결과 캐싱Spring Framework 2021. 8. 11. 17:45
1. 서론 Spring Data Redis와 JPA의 페이징을 이용해서 해당 결과를 캐싱하겠습니다. 2. JPA 페이징 2. 1. query 작성 @Query("from Post") Optional findAllPosts(Pageable pageable); 모든 게시물 목록을 조회합니다 Pageable 인터페이스를 파라미터로 받습니다 2. 2. Test @Test public void findPosts() { Pageable pageRequest = PageRequest.of(0, 10); List posts = postRepository.findAllPosts(pageRequest).orElseThrow(RuntimeException::new); posts.forEach(p -> System.out.p..
-
Entity, DTO 그리고 @ServiceSpring Framework 2021. 7. 13. 22:24
서론 Spring Data JPA를 사용하면서 발생하는 여러 문제들 때문에 Entity와 DTO를 분리하는 과정을 담았습니다. 그리고 이 DTO를 어떻게 스프링 컨테이너가 관리하는 Bean으로 등록할 것인지에 대한 고민을 담았습니다. Entity 사용의 문제점 Post(게시글)이 Board(게시판)의 boardNo(게시판 번호) 참조 1개의 게시판에 여러 개의 게시물 --> 1:N (일대다) 매핑 // 애노테이션 생략 public class Board implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private long..