본문 바로가기

Spring/JPA19

양방향 @OneToOne 문제점과 해결 방법 양방향 @OneToOne 연관관계의 문제점 필자는 Spring Data JPA를 사용할 때, 양방향 @OneToOne 연관관계를 사용하는 걸 굉장히 불편해했다. 왜냐하면 부모 엔터티에서 조회하는 쿼리를 발생시키면, 자식 엔터티와 @OneToOne의 FetchType이 LAZY 연관관계 상태로 설정했음에도 불구하고, 자동으로 자식 엔터티를 SELECT 하는 추가 SQL문이 발생했기 때문이다. 해당 문제점 때문에 부모 엔터티만 필요한 경우에도 자식 엔터티를 가져오면서 리소스 낭비와 성능 저하를 초래했다. 그래서 어쩔 수 없이 양방향 @OneToOne 연관관계가 필요할 때, 비즈니스 로직을 고려해서 최대한 호출이 되지 않을 만한 쪽을 부모 엔터티로 설정하려고 했다. 원인 지연 로딩으로 설정해도 항상 즉시 로딩.. 2024. 10. 30.
@ManyToOne 연관관계에서 부모 엔터티를 등록할 때 프록시 호출을 통해 JPA 최적화 하기 @ManyToOne 연관관계에서 findById()와 getOne()은 JPA(Java Persistence API)에서 엔티티를 조회할 때 사용하는 메서드이다. 이 두 메서드는 각각 다른 방식으로 엔티티를 조회하며, 사용하는 경우도 다르다. 두 메서드의 차이점과 사용 예시 및 최적화 방법에 대해 알아보자.findById() 특징내부적으로 EntityManager의 find()를 사용하며 영속성 컨텍스트, 2차 캐시, DB로 순서로 엔터티를 반환한다. 해당 메서드를 호출하는 경우 SELECT 쿼리가 발생한다. 1. 즉시 로딩 (Eager Loading)findById()는 즉시 데이터베이스 쿼리를 실행하여 엔티티를 조회한다. 데이터베이스에서 해당 엔티티를 즉시 가져오기 때문에, 반환된 객체는 완전히 초기.. 2024. 10. 22.
CascadeType.REMOVE, orphanRemoval=true 특징 JPA에서 엔티티 간의 관계를 설정할 때, CascadeType.REMOVE와 orphanRemoval=true 옵션은 부모 엔티티와 자식 엔티티 간의 삭제 동작을 제어하는 중요한 기능이다. 이 두 옵션은 비슷한 역할을 하지만, 그 동작 방식과 적용되는 상황에서 차이가 있다. 아래에서 각각의 옵션에 대해 상세히 설명하고, 그 차이점을 명확히 하겠다.CascadeType.REMOVE CascadeType.REMOVE는 부모 엔티티가 삭제될 때, 연관된 자식 엔티티도 함께 삭제되도록 하는 옵션이다. 이 옵션은 부모 엔티티의 생명 주기와 자식 엔티티의 생명 주기를 일치시키는 데 사용된다. @Entitypublic class Parent { @Id @GeneratedValue(strategy = Ge.. 2024. 10. 20.
JPA 효과적인 양방향 연관관계 구성방법 양방향 @OneToMany 연관관계는 JPA(Java Persistence API)에서 부모 엔티티와 자식 엔티티 간의 일대다 관계를 설정할 때 사용된다. 이 관계를 효과적으로 구성하기 위해서는 여러 가지 고려사항이 있다.1. 부모 측에서 전이 옵션을 사용해야 한다.전이(cascading)는 항상 부모 엔티티가 자식 엔티티의 생명주기를 관리하도록 한다. 예를 들어, 부모 엔티티를 저장할 때 자식 엔티티도 함께 저장되도록 하려면 CascadeType.ALL 또는 필요한 전이 타입을 설정해야 한다. @Entitypublic class Parent { @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true) pr.. 2024. 10. 16.
JPA Buddy 플러그인을 이용해서 엔티티에 equals와 hashcode를 명시적으로 구현해야 하는 이유 개발하다 보면 엔티티에 equals, hashcode를 구현하기 위해 Lombok 라이브러리를 활용해 @EqualsAndHashCode를 사용하는 경우가 있다. 하지만 이전 포스팅에서 다뤘던 것처럼 Lazy 연관관계를 갖는 엔티티에서  @EqualsAndHashCode를 사용하면 실제 동등성 비교와 테스트 코드에서 문제가 발생할 수 있다. https://shiba-holic.tistory.com/64 JPA에서 Lombok 사용시 주의할 점🤣 배경 프로젝트를 마치고 나면 항상 코드 인스펙션 과정을 통해 프로그램에 대한 취약점이나 장애가 있는지 확인을 하게 되는데, 간혹 equals와 hashcode가 구현되지 않은 엔티티에 대해 경고로shiba-holic.tistory.com이런 경우, 기본 Lombo.. 2024. 6. 22.
[Querydsl] @OneToMany에서 조건 절과 Fetch Join을 함께 사용할 때 서브쿼리 사용하기 배경프로젝트에서 동적 쿼리가 필요한 요구사항을 처리하기 위해 Querydsl를 사용하게 되었다. 쿼리 호출을 최소화하기 위해 1:N 연관관계로 되어있는 데이터를 페치 조인(fetchJoin)으로 가져오려고 했으나, 생각대로 되지 않았다. 필요한건 연관된 목록 전체의 정보인데, 조건에 맞는 데이터 한 건만 가지고 오게 되는 것이었다. 아래는 동일한 상황을 간단하게 재연한 것이다.Shiba@Entity@Table(name = "tb_shiba_holic")@Getterpublic final class Shiba { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "seq") private Long seq; .. 2024. 5. 12.
@Lob 사용시 DB와 엔티티 필드 타입이 다른 경우 발생하는 문제와 해결방법 😫 배경 진행 중인 프로젝트의 과거 코드 중 HTML 문서를 그대로 DB에 저장하는 내용이 있었다. HTML 문서 내용은 동적이고, 길이가 길었기 때문에 긴 문자열 저장을 위해 LOB을 사용했고, 별다른 문제없이 서비스를 이용해 왔었다. 그러다 어느 순간 서비스를 이용할 수 없는 문제가 발생했다. 이와 관련해서 파악한 원인과 해결 방법에 대해서 공유하고자 한다. 🔎 원인 문제 내용을 분석해 보니, 'DB에 선언된 LOB 타입'과 '엔티티에 사용된 @LOB 타입'이 다르게 사용되었기 때문에 발생한 문제였다. 서비스 DB에서는 BLOB 타입을 적용시켰는데, 막상 엔티티 필드에서는 String 타입으로 선언했기 때문에 CLOB 관련 로직이 적용되면서 데이터베이스에서 가져온 데이터를 처리할 수 없게 되어 문제가.. 2024. 1. 7.
JPA @Lob 이해하기 (with MariaDB) LOB 이란? - Large Object의 줄임말로서, 대형 객체 데이터를 저장하기 위한 가변 길이 데이터 유형이다. - BLOB, CLOB 2가지 종류가 있다. * BLOB(Binary Large Object) = 이미지, 오디오, 비디오 같은 이진 데이터를 저장한다. * CLOB = 대량의 텍스트 데이터를 저장한다. 어떻게 사용할까? 이미지, 오디오, 비디오 같은 데이터를 바이너리 형식으로 저장하거나, 대량의 텍스트 값을 저장할 때 사용하면 된다. 엔티티 객체 필드 위에 @Lob이라는 어노테이션을 달면 스프링이 추론하여 어떤 타입으로 저장할지 자동으로 판단한다. 따라서, (1) 데이터베이스에 정의한 컬럼 타입과 (2) 엔티티에 설정하는 타입을 반드시 일치시켜야 한다. (1) 데이터베이스 컬럼 타입 M.. 2024. 1. 6.