JPA에서는 @OneToMany, @ManyToOne을 사용하여 연관관계를 맺을 수 있습니다. 덕분에 객체 지향적으로 DB를 다룰 수 있게 됩니다. 특히나 CRUD 과정을 간소화할 수 있습니다. 그러나 편한만큼 주의해야 할 점도 다양합니다. 이번 주제에서 다룰 순환참조 또한 JPA를 다루면 꼭 마주하는 문제입니다. 순환참조는 두 엔티티가 양방향 연관관계로 설정되어 있을 때 발생합니다. A가 B를 참조하고, B가 A를 참조하게 되면서 무한히 반복됩니다. 순환 참조가 발생하는 예제와 해결하는 방법에 대해서 알아보겠습니다.엔티티 양방향 연관관계 설정User 엔티티패키지 정보 확인하기import jakarta.persistence.Column;import jakarta.persistence.Entity;imp..
OSIV(Open Session In View)란? JPA 하면 떠오르는 것이 영속성 컨텍스트입니다. 영속성 컨텍스트란 DB로부터 조회한 엔티티를 관리하는 저장소라고 생각하면 됩니다. 트랜잭션이 시작되어 조회된 엔티티는 영속성 컨텍스트(1차 캐시)에 저장하여 트랜잭션이 종료될 때까지 사용됩니다. 스프링을 사용한다면 기본적으로 OSIV가 켜진 상태로 사용됩니다. OSIV는 영속성 컨텍스트와 관련이 있는데 이에 대해서 알아보겠습니다. OSIV = true 먼저 사용자의 요청이 들어오면 이것을 처리하기 위해서 트랜잭션이 시작됩니다. 각 트랜잭션마다 영속성 컨텍스트가 생성되고, 트랜잭션이 살아있는 동안 영속성 컨텍스트가 살아있다는 의미가 됩니다. 영속성 컨텍스트가 살아있다면 엔티티의 조회 및 수정을 진행할 수..
Entity 조회 Service 레이어에서 DB에 접근할 때 Transaction 단위로 수행됩니다. 예를 들어, Member 테이블에 id 값이 1인 엔티티가 존재합니다. 해당 엔티티를 조회하기 위해서는 Transaction 단위로 조회해야 합니다. DB에서 엔티티를 조회하기 위해 MemberService를 정의합니다. MemberRepository를 의존성 주입을 받아 사용합니다. @Service public class MemberService { @Autowired MemberRepository memberRepository; @Transactional(readOnly = true) public Member findMember(Long id) { return memberRepository.findB..
Spring Data JPA 기존에 Spring Data JPA가 제공하는 JpaRepository를 상속받았고, 그곳에 사용자 요청을 처리하는 코드들이 담겨있었다. 기존 코드들을 확인해 보자. Service JPAQueryFactory를 의존받아 사용하고 있다. Querydsl로 작성한 쿼리문이 service 레이어에 포함되어 있다. 참고로 select() 절에 QGetSectionResponseDto는 @QueryProjection을 통해 dto로 변환하여 클라이언트로 전달하고자 사용하였다. 서비스 레이어에 쿼리문이 포함되어 있으니 코드 가독성이 좋지 않아 보인다. @Service @RequiredArgsConstructor public class SectionService { private fina..
Cascade란 Cascade란 영속성 전이를 의미한다. 엔티티A에 작업한 내용이 이를 참조하는 엔티티B까지 영향이 전이된다. Cascade에는 여러가지 옵션이 존재한다. ALL // 모두 적용 PERSIST // 영속 REMOVE // 삭제 MERGE // 병합 REFRESH DETACH 위 옵션 중에서 REMOVE에 대해서 알아보겠다. Cascade.REMOVE는 엔티티A를 삭제하면 이를 참조하는 엔티티B도 같이 삭제된다. ex. 부모 엔티티를 삭제하면 모든 자식 엔티티도 같이 삭제된다. 이부분은 사실 직접 경험하지 않는 이상 감이 와닿지 않는다. 나 또한 cascade란 옵션이 있구나? 에서 그쳤었는데, 이번에 무결성 문제가 발생하면서 cascade를 사용해야겠다고 다짐했다. Cascade.REMO..