oneToMany 관계의 엔티티 값들을 일부 변경하여 새롭게 insert하는 방법에 대하여 질문드립니다!
안녕하세요 강사님!
항상 빠르고 명쾌한 답변 감사드립니다:D
강의에서 알려주신 일대 다 관계의 엔티티는 ToOne관계의 데이터들을 조회한 뒤
ToMany관계의 컬렉션들을 따로 조회해서 붙여주는 내용에 대한 실습을 하던 중이였는데요,
여기서 추가로 기존에 DB에 있는 엔티티를 ID값만 바꿔서 새로운 엔티티로 insert하고자 하다가
생각한대로 동작이 잘 안되서 질문드립니다.
여기서 이 엔티티를 insert하고 끝날줄 알았는데 insert가 끝나고 복수의 update문이 실행됩니다ㅠ
이 현상에 대해 아무리 생각해도 모르겠어서 질문드립니다!
아래는 테스트했던 소스코드입니다!
혹시 몰라서 같이 첨부드립니다
[부모 엔티티-TestEntity]
@Entity
@Data
public class TestEntity {
@Id
private String parentId;
private String parentName;
@OneToMany(fetch = FetchType.LAZY,cascade = CascadeType.ALL)
@JoinColumn(name = "parentId")
private List<ChildEntity> childList;
}
[자식 엔티티-childEntity]
@Entity
@Data
public class ChildEntity {
@Id
private String childId;
private String parentId;
private String childName;
}
[Controller]
@RestController
public class TestController {
@Autowired
TestRepository testRepository;
@GetMapping("/entityTest")
public String entityTest(){
List<TestEntity> list=testRepository.selectParentByName("parent");
List<String> idList = list.stream().map(TestEntity::getParentId).collect(Collectors.toList());
Map<String, List<ChildEntity>> collect = testRepository.selectChildList(idList)
.stream().collect(Collectors.groupingBy(ChildEntity::getParentId));
List<TestEntity> result = list.stream().map(
p -> copyParentEntity(p,collect.get(p.getParentId()))
).collect(Collectors.toList());
testRepository.saveAll(result);
return "test";
}
public TestEntity copyParentEntity(TestEntity t,List<ChildEntity> childList){
TestEntity newTest=new TestEntity();
newTest.setParentId("C"+ System.currentTimeMillis()+"_"+t.getParentId());
newTest.setParentName(t.getParentName());
newTest.setChildList(copyChildList(childList,newTest.getParentId()));
return newTest;
}
private List<ChildEntity> copyChildList(List<ChildEntity> childList, String parentId){
ArrayList<ChildEntity> result = new ArrayList<>();
for (int i=0;i<childList.size();i++) {
ChildEntity c=new ChildEntity();
c.setChildId(parentId+i);
c.setParentId(parentId);
c.setChildName(childList.get(i).getChildName());
result.add(c);
}
return result;
}
}
[리포지토리-TestRepository]
public interface TestRepository extends JpaRepository<TestEntity,String> {
@Query("select t from TestEntity t " +
"where t.parentName=:parentName")
List<TestEntity> selectParentByName(@Param("parentName")String parentName);
@Query("select c from ChildEntity c " +
"where c.parentId in :parentIds")
List<ChildEntity> selectChildList(@Param("parentIds")List<String> ids);
}
[DB데이터-parentEntity]
[DB데이터-childEntity]
▶실행결과 로그
1) insert문
insert into test_entity (parent_name, parent_id) values ('parent', 'C1600949255895_1');
insert into child_entity (child_name, parent_id, child_id) values ('child1', 'C1600949255895_1', 'C1600949255895_10');
insert into child_entity (child_name, parent_id, child_id) values ('child2', 'C1600949255895_1', 'C1600949255895_11');
insert into test_entity (parent_name, parent_id) values ('parent', 'C1600949255895_2');
insert into child_entity (child_name, parent_id, child_id) values ('child3', 'C1600949255895_2', 'C1600949255895_20');
insert into child_entity (child_name, parent_id, child_id) values ('chlid4', 'C1600949255895_2', 'C1600949255895_21');
2) update문
update child_entity set parent_id='C1600949255895_1' where child_id='C1600949255895_10';
update child_entity set parent_id='C1600949255895_1' where child_id='C1600949255895_11';
update child_entity set parent_id='C1600949255895_2' where child_id='C1600949255895_20';
update child_entity set parent_id='C1600949255895_2' where child_id='C1600949255895_21';
보시다시피 이미 insert에서 parent_id값들이 다 제대로 들어가고 있는데
같은 값을 set해주는 update문이 실행되고 있어서 왜그런지 모르겠네요...
아니면 혹시 제가 한 방법 외에 엔티티를 복사해주는 좋은 방법이 있다면 알려주시면 감사드리겠습니다ㅠㅠ
바쁘실텐데 긴 글 읽어주셔서 감사합니다!
답변 2
1
오 빠르고 정확한 답변 감사드립니다!
강의는 없었지만 강사님이 쓰신 책에 보니 상세히 적혀있네요ㅎㅎ
참고하겠습니다!
update문 없애겠다고 하루종일 고민했었는데 정말 감사합니다ㅠㅠ
1
안녕하세요. Chung A님^^!
일대다 단방향 매핑을 사용하셨군요!!! 에헴
이렇게 추가로 update가 발생한 것은 복사 때문이 아니라 일대다 단방향 매핑의 특징이면서 단점입니다^^!
일대다 단방향 매핑 대신에 다대일, 일대다 양방향 매핑으로 바꾸어 사용하면 추가 update 쿼리 문제가 해결됩니다.
연관관계 매핑은 설계와 관련된 부분이기 때문에 JPA를 잘 사용하려면 확실히 알아야 하고, 각각의 장단점을 이해해야 합니다.
JPA 기본편 -> 다양한 연관관계 매핑 -> 일대다에서 왜 이런 문제가 발생하는지, 그리고 대안은 어떤 것들이 있는지 매우 자세하게 설명드립니다.
혹시 JPA 기본편을 듣지 않으셨다면, 지금 시점에 한번 JPA 기본편을 듣는 것을 추천드립니다^^!
감사합니다.
강의 관련 외 질문입니다.
0
64
2
SpringBoot4 + Hibernate7 모듈 등록 방법 공유
0
85
1
BeanCreationException
0
86
3
Update 후 UpdateMemberResponse 매핑할 때
0
46
1
트랜잭션을 사용 안 할 때 커넥션은 언제 가져오나요?
0
98
2
페이징 + 검색조건 관련해서 질문드립니다.
0
70
1
Query Dsl Q파일 질문입니다.
0
81
1
루트 쿼리라는것은
0
58
1
메서드를 분리하는 기준
0
61
1
findAllWithMemberDelivery 메서드 질문드립니다.
0
108
3
연관관계 매핑을 안 쓸 경우, 사용해야 하는 전략
0
83
2
fetch join과 영속화와 OSIV의 관계
0
83
2
Distinct 사용 전 결과에 대한 의문
0
113
2
레포지토리 계층에서의 트랜잭션에 대한 의문
0
55
1
영속성 컨텍스트 생명주기의 신기한 부분이 있습니다.
0
77
2
dto 필드 속 엔티티 여부
0
58
1
뷰템플릿 사용 시
0
76
2
Result 클래스 관련 질문
0
56
1
@PostConstruct 프록시 관련 질문드립니다
0
85
1
DTO 대신 Form 사용은 안되나요?
0
133
1
OSIV ON 상태일 때
0
95
1
fetch join VS fetch join 페이징 궁금증
0
179
2
양방향 연관관계 알아보는 법?
0
104
1
16강 17강 간단 정리 이게 맞을까요 ?
0
165
2





