작성
·
372
1
안녕하세요. 공부하다 헷갈리는 부분이 있어서 질문드립니다.
제가 알기로는 persist를 실행을 해도 트랜잭션이 끝날 때 쿼리가 나가면서 insert가 되는 걸로
알고 있습니다.
그래서 아래 사진과 같은 테스트를 해봤습니다.
@Slf4j
@SpringBootTest
@Transactional
@Commit
class CategoryRepositoryImplTest {
@Autowired
CategoryRepository categoryRepository;
@Autowired
EntityManager em;
@Test
void save() {
Category category = new Category("상의", 1, null);
category.addDate(LocalDateTime.now(), LocalDateTime.now());
em.persist(category);
log.info("=================================");
}
}
save를 실행해보았더니 로그가 아래와 같이 찍힙니다.
2023-02-16 22:43:53.648 DEBUG 8220 --- [ main] org.hibernate.SQL :
insert
into
t_category
(mod_date, reg_date, depth, name, parent_id)
values
(?, ?, ?, ?, ?)
2023-02-16 22:43:53.684 INFO 8220 --- [ main] s.s.r.c.CategoryRepositoryImplTest : =================================
persist를 날리면 메소드가 끝날 때 트랜잭션이 끝나기 때문에 insert쿼리가 로그보다 먼저 찍히면 안될 것 같은데 로그에는 그렇게 찍히니 조금 혼란스럽습니다.
현재 저 프로젝트는 jpa, spring data jpa, querydsl 를 같이 사용하고 있습니다.
왜 저렇게 동작되는지 원인을 알 수 있을까요?
혹시나 해서 관련된 테이블 category클래스와 dateColumn 클래스도 캡처하겠습니다.
@Entity
@Table(name = "T_CATEGORY")
@Getter
@NoArgsConstructor(access = PROTECTED)
public class Category extends DateColumns {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "CATEGORY_ID", nullable = false)
private Long id;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private Integer depth;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "PARENT_ID")
private Category parent;
public Category(String name, Integer depth, Category parent) {
this.name = name;
this.depth = depth;
if(depth > 1) {
this.parent = parent;
}
}
}
@MappedSuperclass
@Getter
public class DateColumns {
@Column(name = "REG_DATE", updatable = false, nullable = false)
private LocalDateTime regDate;
@Column(name = "MOD_DATE", nullable = false)
private LocalDateTime modDate;
public void addDate(LocalDateTime reg, LocalDateTime mod){
regDate = reg;
modDate = mod;
}
}
답변 2
3
안녕하세요,
em.persist 시 동작은 엔티티의 primary key 생성 전략(@GeneratedValue(strategy=xxx))에 따라 달라집니다.
GenerationType.IDENTITY
기본 키 생성을 데이터베이스에 위임합니다.
따라서 em.persist() 시점에 즉시 insert sql을 실행하고 db에서 식별자를 받아옵니다.
GenerationType.SEQUENCE
GenerationType.TABLE
3개 방식 중 아래의 2개 방식이 트랜잭션 시점에 실제 insert 쿼리를 발생 시키게 됩니다.
자세한 내용은 수업 "엔티티 매핑 | 기본 키 매핑"에 있습니다~
2
안녕하세요^^
기본 키 매핑 전략 IDENTITY
IDENTITY
전략은 em.persist()
시점 즉시 INSERT SQL
실행하고 DB
에서 식별자를 조회합니다.
영속성 컨텍스트에 관리되려면 PK
가 무조건 있어야 하기 때문에 commit
에 SQL
이 날아가지 않습니다.
따라서 em.persist()
는 쓰기 지연 SQL 저장소를 사용할 수 없습니다.
감사합니다.^^