• 카테고리

    질문 & 답변
  • 세부 분야

    백엔드

  • 해결 여부

    미해결

새로운 엔티티가 기본 키 직접 할당 전략을 사용하는 경우 변경 감지로 새로운 엔티티를 추가할 때 merge가 발생하는지?

22.12.03 16:37 작성 조회수 329

0

 

새로운 엔티티를 구별하는 방법에 대해 강의를 듣다가 기존 영속성 엔티티에 비영속성 엔티티를

추가하고 CascadeType.ALL을 통해 비영속성 엔티티를 저장할 때

비영속성 엔티티가 기본 키를 직접 할당하는 전략을 사용하면 의도하지 않은 merge가 발생할 것 같아서 테스트를 진행하고 있습니다.

 

추가적으로 ..
Team 엔티티를 저장한 이후 새로운 Member 엔티티를 추가하는 과정에서 @Rollback(value=false)를 주지않으면 Member 엔티티의 insert문이 발생하지 않아서 이 부분도 추가적으로 궁금합니다.

 

@ToString @Getter
@Entity @NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Team {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToMany(mappedBy = "team", cascade = CascadeType.ALL)
    private List<Member> members = new ArrayList<>();

    private String name;

    public void addMember(Member member) {
        member.setTeam(this);
        members.add(member);
    }

    @Builder
    private Team(String name) {
        this.name = name;
    }
}


@ToString(exclude = "team")
@Getter @Setter
@Entity @NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Member extends BaseEntity{

    @Id
    private Long id;
    private String username;
    private Integer age;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "team_id")
    private Team team;

    @Builder
    private Member(Long id,String username, Integer age, Team team) {
        this.id = id;
        this.username = username;
        this.age = age;
        this.team = team;

    }

}

 

테스트 코드는 다음과 같습니다.

 

@SpringBootTest
class TeamJpaRepositoryTest {

    @Autowired
    private TeamJpaRepository teamJpaRepository;

    @Autowired
    private EntityManager em;


    @BeforeEach
    void beforeEach() {
        Team aTeam = Team.builder()
                .name("A Team")
                .build();
        teamJpaRepository.save(aTeam);
        em.clear();
    }

    @Test
    @Transactional
    public void saveMember() throws Exception {
        //given
        Member userA = Member.builder()
                .id(10L)
                .age(10)
                .username("user A")
                .build();

        //when
        Team savedTeam = teamJpaRepository.findByName("A Team");
        savedTeam.addMember(userA);
        //then

    }
}

 

  1. 왜 savedTeam에 대해 변경 감지에 대해 @Rollback(value=fasle) 어노테이션이 없으면 Member insert문이 발생하지 않는지 궁금합니다.



    스프링 데이터 JPA의 쿼리 메소드의 구현체가 @Transaction(readOnly = true)라고 해도 최초 트랜잭션이 readOnly 옵션이 false이기 때문에 트랜잭션 전파의 문제는 아닌 것 같아서요.

    @Rollback 옵션을 주었을 때 로그는 다음과 같습니다.


  2. 처음에 궁금했던 Team 엔티티에 새로운 Member 엔티티를 직접 기본 키를 할당하여 저장할 때
    해당 로그를 보면 merge가 발생하지 않는 것 같습니다.
    Persistable 인터페이스의 isNew 메소드를 오버 라이드하지 않았는데 말이죠.

    이 부분에 대해서 궁금합니다.

    plugins { id 'java' id 'org.springframework.boot' version '2.7.5' id 'io.spring.dependency-management' version '1.0.15.RELEASE' }

답변 1

답변을 작성해보세요.

0

안녕하세요. chinggin님

스프링에 테스트에 @Transactional을 적용하면 기본은 롤백을 해버리게 됩니다.

이렇게 롤백을 해버리면 JPA의 영속성 컨텍스트를 플러시 하지 않게 됩니다.

테스트에서 @Rollback(false)를 지정하면 강제로 커밋을 호출하게 되어 플러시가 발생합니다. 그래야 sql이 db에 전송됩니다.

감사합니다.

chinggin님의 프로필

chinggin

질문자

2022.12.05

감사합니다.

추가적으로 2번 질문인데요.

Team 엔티티에 새로운 Member 엔티티를 직접 기본 키를 할당하여 저장할 때 영속성 컨텍스트에 새로운 멤버를 저장하는데, 기본 키가 있으니 merge가 발생할 것 같은데 persist가 발생하는 이유는 무엇일까요?

 

 

변경 감지를 통해 연관된 엔티티를 저장하는 방식은 기본설정인 기본 값이 null 여부로 확인하지 않고 무조건 persist하는 건가요?

안녕하세요. chinggin님

2번 부분은 코드로 확인이 더 필요할 것 같아요.

전체 프로젝트를 압축해서 구글 드라이브로 공유해서 링크를 남겨주세요.

구글 드라이브 업로드 방법은 다음을 참고해주세요.

https://bit.ly/3fX6ygx

주의: 업로드시 링크에 있는 권한 문제 꼭 확인해주세요

추가로 다음 내용도 코멘트 부탁드립니다.

1. 실행 방법을 알려주세요.

2. 어떻게 문제를 확인할 수 있는지 자세한 설명을 남겨주세요.

감사합니다.