본문 바로가기

jpa18

스프링 @ExceptionHandler 를 통한 예외 처리 스프링으로 프로젝트를 진행하다 보면 정해진 입력값이 잘못되거나 없거나 하는 등 다양한 예외들이 발생할 것이다. 아래와 같이 흔히 JPA로 데이터를 가져올 때도 findById를 사용할 때 잘못될 경우를 대비하여 exception을 던질 것이다. User user = userRepository.findById(user.getId()) .orElseThrow(() -> new IllegalStateException( "userId가 " + user.getId() + "인 user를 찾지 못했습니다.")); 그렇다면 위에 코드처럼 findById를 통해 데이터를 가져오려고 했지만 예외가 발생했을 때에는 클라이언트한테는 어떻게 표시될까? 뭐라고 하는지도 모를 이상한 에러가 보여질 것이다. 그렇기에 이러한 예외들.. 2021. 10. 2.
JPA - 읽기 전용으로 데이터를 조회하여 성능 향상(메모리, 속도) 들어가기 JPA를 사용하면서 영속성 컨텍스트를 통해 1차 캐시 및 쓰기 지연 등 여러 가지 이점을 얻을 수 있었다. 그런데 조회 기능만을 사용하는 상황에서는 단순히 읽기 전용 기능으로 데이터를 조회만 가능하게 하고 데이터의 수정을 불가능하게 할 수 있다고 한다. 이런 방식을 적용하면 두 가지 장점을 얻을 수 있다. 바로 메모리와 속도의 최적화이다. 메모리 사용량을 최적화하는 읽기 전용 기능과 속도를 최적화하는 읽기 전용 기능은 각각 다른 방식으로 구현된다. 이 글은 메모리와 속도를 최적화하기 위한 읽기 전용 기능에 대해 작성한 글이다. 영속성 컨텍스트에 대한 내용이 많이 나오는데, 이에 대한 것은 https://khdscor.tistory.com/110를 참고하길 바란다. 메모리 최적화 먼저 메모리 사용.. 2021. 9. 18.
SpringBoot Controller Test 작성 및 spring-security에서의 test 프로젝트를 진행할 때 Test를 진행하는 것이 매우 중요하다. 그 이유는 백엔드로서 코드를 작성하면 그 코드가 올바르게 동작하는지 확실히 해야 하기 때문이다. repository 함수가 제대로 동작하는지, service가 제대로 동작하는지, controller이 제대로 동작하는지 등을 확인해야 한다. 여기서는 controller test를 살펴볼 것이다. controller를 만들고 제대로 작동되는지 확인하기 위해서는 test코드를 작성하지 않는다면 post나 put 같은 기능을 일일이 웹에서 실행을 하고 이것저것 시도하는 것을 서버를 켜고 해야 하는 번거로움이 있다. 그렇기에 test코드를 작성하는 것이 바람직하다. 아래는 간단한 post에 대한 코드이다. PostsApiController import.. 2021. 8. 31.
JPA 두번 이상의 left join fetch가 필요할 때 해결 방법(MultipleBagFetchException 문제 해결) 프로젝트를 진행하면서 두개 이상의 OneToMany 리스트를 가진 객체에 대한 정보를 가져올 때 N+1 문제에 걸리지 않으면서 각각의 리스트들을 가져올 필요가 있었다. 만약 하나의 OneToMany 리스트만을 같이 다룬다면 left join fetch 를 적용하여 해결할 수 있다. 하지만 문제는 두 개의 리스트라는 점이다. left join fetch는 두 번 이상 사용할 수 없다.(OneToOne는 가능하다) 이는 잘못하면 카티젼 곱과 같은 형식으로 데이터가 전달될 위험이 있기 때문에 서버는 미리 MultipleBagFetchException 를 띄우며 에러처리를 한다. 그렇다면 이러한 상황에서 어떻게 해야할까? 이는 한번의 select – from where a=b절을 select – from whe.. 2021. 8. 23.
JPA setter을 만들지 않아야 하는 이유 나는 JPA 엔티티를 만들면 항상 getter, setter을 만들었었다. 하지만 setter는 사용하지 않는 게 좋다고 한다. 이 글은 그 이유를 간단하게 기록해본 것이다. JPA에서 데이터 타입은 크게 값 타입과 엔티티 타입으로 나뉜다. 여기서 값 타입은 기본값 타입, 임베디드 타입, 컬렉션 값 타입 으로 나뉘고 기본값 타입은 자바 기본 타입(int, double), 래퍼 클래스(Integer), String 로 나뉜다. 엔티티를 구성할 때 값 타입으로 구성하는 경우가 많은데 각 값 타입은 다른 엔티티들과 공유를 하면 위험하다. 한 엔티티에서 다른 엔테티의 값을 변경하면 위험하기 때문이다. 일반적인 자바 기본 타입은 값을 대입하면 복제가 이뤄진다. 하지만 임베디드 타입같은 객체형식의 값타입은 값을 대.. 2021. 7. 22.
JPA 임베디드 타입 JPA의 데이터 타입은 크게 값 타입과 엔티티 타입으로 나눈다. 값 타입은 기본값 타입, 임베디드 타입(복합 값 타입), 컬렉션 값 타입으로 나뉘고 엔티티 타입은 @Entity로 정의하는 객체이다. 기본 값 타입은 자바 기본 타입(ex. int, double), 래퍼 클래스(ex. Integer), String 로 구성된다. 먼저 임베디드 타입부터 설명하겠다. 임베디드 타입은 JPA에서 새로운 값 타입을 정의할 수 있도록 구현한 것이다. 즉 임베디드 타입도 int나 double와 같은 값 타입 이라는 것이다. 아래의 예시를 보자. @Entity @AllArgsConstructor @NoArgsConstructor @Getter @Builder public class Article { @Id @Genera.. 2021. 7. 22.
JPA - 프록시와 연관관계(즉시로딩, 지연로딩, N + 1 문제) 들어가기 JPA는 데이터 베이스에 있는 객체를 가져올 때 우선 영속성 컨텍스트에 가져오게 된다. 그렇다면 그 객체와 연관된 객체를 가져올 때 어떻게 가져오는가?경우는 두 가지가 있다.첫 번째는 그 연관된 객체도 미리 영속성 컨텍스트에 올려놓는 것이다. 이 방식을 즉시 로딩이라 한다.두 번째는 그 연관된 객체를 사용하는 시점에 가져오는 것이다. 이 방식을 지연 로딩이라 한다.이 글에서는 이러한 두 가지 로딩 방식에 대해서 '프록시 객체'와 함께 설명할 것이다. 영속성 컨텍스트에 대한 내용이 많이 나오는데, 이에 대한 것은 https://khdscor.tistory.com/110를 참고하길 바란다.   본론 지연 로딩을 이용하기 위해선 실제 객체 대신에 데이터 베이스 조회를 지연할 수 있는 가짜 객체가 필요.. 2021. 7. 19.
JPA 객체 매핑- 연관 관계 1. 겍체와 테이블의 연관관계 방식 객체 연관관계로 따지면 Member 객체는 Member.team 필드로 Team 객체와 참조(주소)로 단방향 연관관계를 맺으며 member는 team필드로 Team을 알 수 있지만 Team은 Member을 알 수 없다. 테이블로 따지면 양방향 연관관계이다(단반향이 없다). MEMBER 테이블의 TEAM_ID 외래 키를 통해 TEAM과 MEMBER은 서로 조인 할 수 있기 때문이다. 2. 연관 관계 매핑JPA를 사용해서 객체방식과 테이블 방식을 매핑한다. Member 객체에 아래처럼 작성한다. @ManyToOne @JoinColumn(name="TEAM_ID") private Team team; Member.team 과 MEMBER.TEAM_ID 를 매핑하는 것이 연관관.. 2021. 7. 8.
JPQL 개념과 스프링 데이터 JPA 쿼리메서드 이용 JPA를 사용하여 프로젝트를 구현할 때 스프링 데이터 JPA를 이용하고 repository 인터페이스를 작성하여 CRUD기능을 사용하였을 것이다. 우리는 JPA를 사용하기 위해 Repository를 만들고 CRUD기능을 수행할 수 있다. 하지만 간단한 형식의 엔티티만을 가져올 뿐이지 특정 범위, 특정 경우, 특정 순서 등 복잡한 경우에 적용하기는 힘들다. 이러한 경우는 자세한 sql문을 이용해서 해결할 수 있다. ORM은 엔티티 객체를 대상으로 개발하므로 검색을 위한 sql문도 엔티티 객체를 대상으로 해야 하기에 JPQL을 사용한다. 스프링 데이터 JPA에서는 복잡한 쿼리를 쿼리 메서드를 이용하여 JPQL을 직접 짜는 것이다. 이 글에서는 JPQL에 대해서는 간단한 설명과 파라미터 바인딩에 대해서만 설명.. 2021. 6. 27.