oneToMany 관계의 엔티티 값들을 일부 변경하여 새롭게 insert하는 방법에 대하여 질문드립니다!

해결됨
Chung A 프로필

안녕하세요 강사님!

항상 빠르고 명쾌한 답변 감사드립니다: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문이 실행되고 있어서 왜그런지 모르겠네요...

 

아니면 혹시 제가 한 방법 외에 엔티티를 복사해주는 좋은 방법이 있다면 알려주시면 감사드리겠습니다ㅠㅠ

바쁘실텐데 긴 글 읽어주셔서 감사합니다! 

김영한 프로필
김영한 1달 전

안녕하세요. Chung A님^^!

일대다 단방향 매핑을 사용하셨군요!!! 에헴

이렇게 추가로 update가 발생한 것은 복사 때문이 아니라 일대다 단방향 매핑의 특징이면서 단점입니다^^!

일대다 단방향 매핑 대신에 다대일, 일대다 양방향 매핑으로 바꾸어 사용하면 추가 update 쿼리 문제가 해결됩니다.

연관관계 매핑은 설계와 관련된 부분이기 때문에 JPA를 잘 사용하려면 확실히 알아야 하고, 각각의 장단점을 이해해야 합니다.

JPA 기본편 -> 다양한 연관관계 매핑 -> 일대다에서 왜 이런 문제가 발생하는지, 그리고 대안은 어떤 것들이 있는지 매우 자세하게 설명드립니다.

혹시 JPA 기본편을 듣지 않으셨다면, 지금 시점에 한번 JPA 기본편을 듣는 것을 추천드립니다^^!

감사합니다.

Chung A 프로필
Chung A 1달 전

오 빠르고 정확한 답변 감사드립니다!

강의는 없었지만 강사님이 쓰신 책에 보니 상세히 적혀있네요ㅎㅎ

참고하겠습니다!

update문 없애겠다고 하루종일 고민했었는데 정말 감사합니다ㅠㅠ 

지식공유자 되기
많은 사람들에게 배움의 기회를 주고,
경제적 보상을 받아보세요.
지식공유참여
기업 교육을 위한 인프런
“인프런 비즈니스” 를 통해 모든 팀원이 인프런의 강의들을
자유롭게 학습하는 환경을 제공하세요.
인프런 비즈니스