작성
·
503
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
}
}
왜 savedTeam에 대해 변경 감지에 대해 @Rollback(value=fasle) 어노테이션이 없으면 Member insert문이 발생하지 않는지 궁금합니다.
스프링 데이터 JPA의 쿼리 메소드의 구현체가 @Transaction(readOnly = true)라고 해도 최초 트랜잭션이 readOnly 옵션이 false이기 때문에 트랜잭션 전파의 문제는 아닌 것 같아서요.
@Rollback 옵션을 주었을 때 로그는 다음과 같습니다.
처음에 궁금했던 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님
2번 부분은 코드로 확인이 더 필요할 것 같아요.
전체 프로젝트를 압축해서 구글 드라이브로 공유해서 링크를 남겨주세요.
구글 드라이브 업로드 방법은 다음을 참고해주세요.
주의: 업로드시 링크에 있는 권한 문제 꼭 확인해주세요
추가로 다음 내용도 코멘트 부탁드립니다.
1. 실행 방법을 알려주세요.
2. 어떻게 문제를 확인할 수 있는지 자세한 설명을 남겨주세요.
감사합니다.
감사합니다.
추가적으로 2번 질문인데요.
Team 엔티티에 새로운 Member 엔티티를 직접 기본 키를 할당하여 저장할 때 영속성 컨텍스트에 새로운 멤버를 저장하는데, 기본 키가 있으니 merge가 발생할 것 같은데 persist가 발생하는 이유는 무엇일까요?
변경 감지를 통해 연관된 엔티티를 저장하는 방식은 기본설정인 기본 값이 null 여부로 확인하지 않고 무조건 persist하는 건가요?