JPA 자식 엔티티를 저장/삭제하는 방법
786
작성한 질문수 6
안녕하세요.
JPA 강의를 수강하고, 실무에서 적용해보던 중 의문점이 생겨 질문드립니다.
강의에서는 엔티티의 변경 시에는 JPA의 Dirty Checking을 사용하라고 하셨는데요.
그렇다면 실제 JPA를 사용하는 실무에서도 새로운 하위 엔티티를 DB에 저장/삭제해야하는 경우에 상위 엔티티에서 하위 엔티티를 컬렉션에 add/remove 하는 방식을 통해 변경감지를 이용하여 저장하나요?
(이 경우에 자식 엔티티를 add 하기 위해 모든 자식 엔티티들을 Lazy Loading 하는 비효율이 발생할 것 같아 질문 드립니다.)
설명하기 쉽게 코드와 함께 질문을 정리해보겠습니다.
엔티티 코드는 다음과 같습니다. (편의 상 최대한 간추렸습니다.)
@Entity
public class Team {
@Id
private Long id;
@OneToMany(mappedBy = "team")
private List<Member> members = new ArrayList<>();
public void addMember(Member member) {
this.members.add(member); <-- 자식 엔티티들을 모두 조회하는 LAZY LOADING 발생!
}
}
@Entity
public class Member {
@Id
private Long id;
@JoinColumn(name = "team_id")
@ManyToOne()
private Team team;
}
<트랜잭션 계층>
public void createMember(Member newMember) {
Team team = teamRepository.findById(1L);
team.addMember(newMember); <-- 자식 엔티티들을 모두 조회하는 LAZY LOADING 발생!
}
이 경우 변경감지를 통해서 하위 엔티티를 저장할 수 있고, 더 객체지향 관점에 맞는 방법 같지만 Member 하나를 추가하기 위해 Team에 속한 모든 Member를 조회해오는 비효율이 발생할 것 같습니다.
setTeam(team)으로 team과 연관관계를 맺어준 뒤, memberRepository.save(member)로 저장하면, 불필요하게 모든 member를 조회하지 않아도 될 것 같은데, 실무에서는 어떤 방법으로 엔티티를 저장/삭제하는 지 궁금해서 질문드립니다!
마찬가지로 연관관계 메서드도 자식엔티티와의 연관관계를 맺기 위해 자식엔티티들을 모두 LAZY LOADING (members.add(team) 시 자식 엔티티들을 모두 조회)해야 하나요?
감사합니다.
답변 1
0
안녕하세요, 인프런 AI 인턴입니다.
개발맨님, JPA에서 새로운 하위 엔티티를 저장하거나 삭제할 경우, 질문에서 언급하신 것처럼 컬렉션에 add/remove를 통해 변경 감지를 사용하는 방법은 하나의 옵션입니다. 하지만 실제로 LAZY LOADING으로 인한 성능 이슈를 고려해야 하는 경우가 많습니다.
CrudRepository.save(…) 메서드는 엔티티가 아직 영속화되지 않은 경우 entityManager.persist(…) 메서드를 호출하여 저장하고, 이미 영속화된 경우 entityManager.merge(…) 메서드를 호출하여 엔티티를 병합합니다(Spring Data JPA 문서 참조). 이 메소드를 사용하여 각각의 엔티티를 개별적으로 저장함으로써 LAZY LOADING을 트리거하지 않는 접근 방식을 선택할 수도 있습니다.
실무에서는 상황에 따라 적절한 접근을 선택해야 하는데, 자식 엔티티를 개별적으로 저장하고 삭제하기 위해 명시적으로 save나 delete를 호출하는 것이 더 바람직할 수 있습니다. 특히, 대량의 데이터를 처리해야 할 때는 JPA의 벌크 연산을 사용하여 성능을 최적화할 수 있습니다. 예를 들어, Spring Data JPA에서는 @Modifying어노테이션과 함께 @Query를 사용하여 벌크 삭제를 수행할 수 있습니다(Derived Delete Queries 문서 참조).
interface UserRepository extends Repository<User, Long> {
@Modifying
@Query("delete from User u where u.role.id = ?1")
void deleteInBulkByRoleId(long roleId);
}
이러한 벌크 연산은 개별 엔티티에 대한 변경 감지나 라이프사이클 이벤트를 트리거하지 않기 때문에 성능이 중요한 상황에서 유용할 수 있습니다.
부모 엔티티의 컬렉션에서 자식 엔티티를 추가하거나 제거할 때 LAZY LOADING으로 인한 모든 자식 엔티티의 로딩 문제를 완전히 피하기는 어렵지만, 자식 엔티티가 많지 않은 경우나 성능에 큰 영향을 미치지 않는 경우에는 객체지향적인 설계 관점에서 변화를 감지하는 방식을 사용하는 것이 코드의 명확성과 유지보수성을 높일 수 있습니다.
최종적으로 채택할 방법은 애플리케이션의 요구사항, 성능 목표, 유지보수성 및 팀의 경험에 따라 결정되어야 합니다. 따라서 두 가지 접근 방식 모두 고려하여 그 장단점을 비교한 뒤 상황에 맞는 최적의 해결책을 선택하는 것이 중요합니다.
실무에서의 경험을 공유하는 것도 도움이 될 수 있으니 커뮤니티나 동료 개발자와 교류하며 노하우를 쌓는 것도 추천합니다.
감사합니다.
Inner class로 Config를 지정하는 이유
0
29
1
Part 2 듣기전 복습하던 중, 아키텍처에 관한 질문이 있습니다.
0
47
2
테스트는 인터페이스를 대상으로 만드는것에 대해 궁금한 점이 있습니다.
0
32
1
리뉴얼 시기
0
53
2
JPA 엔티티로 만들었다고 기술종속이 아닌지에 대한 질문
0
56
3
설계 트레이드 오프 링크 접속 안됨
0
85
2
테스트 질문, 어떤것을 사용할것인것에 대해서
0
46
1
service-discovery 프로세스 가동 이유
0
51
1
트래잭션 전파 기본- 에 대한 개념 질문? 이렇게 생각해도 맞나요?
0
47
1
헥사고날 아키텍처와 DDD를 적용할 때, 화면에 강하게 연관된 조회 데이터를 어떻게 다루는 게 좋은지 궁금합니다.
0
132
2
h2 database
2
59
2
Request DTO에서 Entity를 생성할 때 의존성 방향을 반대로 하면 어떨까요?
0
116
2
Querydsl 설정 할때 - run and test 다르게 설정 할때? 질문
0
61
1
new 패키지명.Dto명 생략가능
0
74
2
변경감지(더티체킹) 이후 플러시할 경우의 쿼리
0
73
1
단일 테이블 시 null 값과 연관관계 필요성 질문
0
65
1
SpringBoot4 버전 Hibernate5JakartaModule 라이브러리 오류
0
64
1
aws 관련 질문드립니다.
1
69
3
setter 사용하지 않기
0
61
1
안녕하세요 토비님 혹시 완성된 코드의 repository 주소는 없을까요?
0
127
2
자막 오타 제보
0
54
1
rabbitmq에 configservice 연결에 대해 질문있습니다.
0
65
1
안녕하세요 치킨 디도스 이벤트 보고 흉내내보려 들어왔습니다..
0
74
2
join에대해 질문드립니다.
0
55
1





