persist()할 때 insert문이 왜 발생할까요?

토닉·2022년 10월 8일
0
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
public class Cycle {

    public static final long DAYS = 3L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "cycle_id")
    private Long id;

		// member, challenge와 다대일 관계로 매핑 .. 필드 생략

    @OneToMany(mappedBy = "cycle", cascade = {CascadeType.PERSIST, CascadeType.REMOVE})
    @BatchSize(size = 10)
    private List<CycleDetail> cycleDetails = new ArrayList<>();

    @Enumerated(EnumType.STRING)
    @Column(nullable = false)
    private Progress progress;

		public void increaseProgress(LocalDateTime progressTime, Image progressImage, String description) {
			this.progress = progress.increase(startTime, progressTime);
			if(this.cycleDetails.size() <= 2) {
				this.cycleDetails.add(new CycleDetail(this, progressTime, progressImage.getUrl(), description, progress));
			}
		}

Cycle이라는 엔티티는 CycleDetail과 일대다 관계를 맺고 있습니다. 여기서 increaseProgress() 를 실행하면 다음과 같이 쿼리문이 발생합니다.

위 처럼 쿼리문이 발생하는데 뭔가 이상하지 않나요?

위 메서드는 service에서 트랜잭션이 시작되고 커밋하면서 영속성 컨텍스트를 flush하게 됩니다. flush하면 영속성 컨텍스트의 변경 감지로 인해 Cycle의 progress에 대한 update 쿼리, CycleDetail에 대한 insert 쿼리 순으로 날라갈 것이라고 예상됩니다. 그런데 왜 CycleDetail 에 대한 insert 쿼리문이 먼저 발생할까요?

GenerationType.IDENTITY

Identity 식별자 생성 전략을 @GeneratedValue(strategy = GenerationType.IDENTITY) 으로 했기 때문입니다. 영속성 컨텍스트에서 엔티티를 관리하려면 식별자가 필요합니다. 그런데 위 식별자 생성 전략은 데이터베이스에 의존하게 되는데요. 그럼 어쩔 수 없이 데이터베이스에 접근하여 id를 가지고 와야 합니다. 따라서 엔티티를 영속화할 때 Insert문을 날리게 됩니다.

Cycle cycle = new Cycle(member, challenge, Progress.NOTHING, now);
entityManager.persist(cycle);

Ref

[JPA] Auto Increment가 포함된 Insert쿼리는 언제 나갈까?

profile
우아한테크코스 4기 교육생

0개의 댓글