개발환경은 vscode, openjdk11, springboot, JPA
테이블 A의 데이터를 실시간 성으로 집계하여 테이블B에 넣는 배치개발에 대한 요구사항이 왔다.
A와 B의 테이블 구조는 거의 동일하나 B에는 A에 없는 컬럼이 몇개 더 있고 PK가 달랐다.
실시간 성으로 동작하여야 했기 때문에 배치를 QuartzScheduler로 매분 돌리는 무식한 방법은 pass
JPA를 사용하고 있었기에, @PostPersist @PostUpdate @PostRemove로 해결코자
@EntityListener를 추가하였다.
@Entity
@IdClass(EntityAId.class)
@Table(name="tb_entity_a")
@NoArgsConstructor
@Getter
@Setter
@EntityListeners(EntityAListener.class)
public class EntityA {
//(생략)
}
그리고 리스너는 아래와 같이 개발하였다.
@Service
@Transactional
public class EntityAListener{
@Autowired
private ApplicationContext applicationContext;
//바로 TbEntityBRepository를 Autowired를 하면 null로 찍힌다.
@PostPersist
@PostUpdate
@PostRemove
public void postPersist(EntityA eta) {
TbEntityBRepository tbEntityBRepository = applicationContext.getBean(TbEntityBRepository.class);
//(생략)
EntityB etb = new EntityB();
//(생략)
tbEntityBRepository.save(etb);
//(생략)
}
}
결과는?
콘솔의 hibernate 에 tbEntityBRepository.save(etb)가 실행되면서
우선 select 문은 찍혔는데 정작 insert가 되지 않고 SQL이 찍히지도 않았다.
??
왜죠?
해매다가 EntityB에 먼저 넣어보자는 생각으로
어노테이션들을 Post -> Pre로 변경했더니 잘되는것이었다.
다만 Insert외에 Update, Delete에서는 동일한 현상이 있어 삭제 후 Insert를 위해 추가적으로 @PostLoad를 만들었다.
//(생략)
@PrePersist
@PreUpdate
@PreRemove
public void postPersist(EntityA eta) {
//save
}
@PostLoad
public void postLoad(EntityA eta) {
// 기존 리포지토리 데이터 삭제
}
EntityA 에 넣기전이면 Pre... 넣은 후면 Post라고 생각을 해서 Post를 사용한것이 문제였고
하나의 트랜잭션에서 JpaRepository save 가 한번 완료되면 다른 JpaRepository로의 insert가 되지 않는 것으로 마무리
728x90
'개발 > java' 카테고리의 다른 글
| Logbook 으로 access log 남기기 (2) | 2024.01.04 |
|---|---|
| mybatis interceptor 암복호화 처리 (1) | 2023.12.13 |
| Runtime에서 annotation attribute 변경 - influxDB @Measurement 공통 DTO 만들기 (1) | 2022.09.07 |
| vscode debugger에서 java.lang.ExceptionInInitializerError 잡기 (0) | 2022.09.07 |
| CutomException 처리 (1) (0) | 2022.07.07 |