hibernate 공식 문서
Entity Life Cycle
(Persist, Remove, Update, Load) 에 대한 이벤트 발생 시 call back 처리
Pre
- vs Post
-
@PreUpdate callback is only called if the data is actually changed
즉 @PreUpdate는 실질적으로 Update SQL문이 실행될 때 동작한다. (트랜잭션 종료 or flush 하는 시점)
트랜잭션 바운더리 안에서 실행되기 때문에 영속성 컨텍스트에 의해 관리됨
@PreUpdate가 동작할 때 DB에서 변경되는 값을 조회할지라도, 이미 변경된 값으로 조회가 되기 때문에 결과적으로 행위 자체는 @PostUpdate와 동일한 결과
-
알림
를 보내주는 곳(저장 시점)이 산발적으로 흩어져있어서, 소켓을 전송하는 각 모듈 하나하나에 추가하는데 시간이 오래걸리고 반복적인 작업 → 생산성이 저하되며, 코드가 반복됨 -
현재의 요구사항 : 알림 객체가 Persist 되는 시점에 Socket으로 알림을 보내준다고 추상화할 수 있다.
→ 따라서, NoticeListener 생성하여 Socket 알림 전송을 처리한다.
@Slf4j
public class NoticeListener {
@PostPersist
public void sendSocketNotice(Notice notice) {
SimpMessagingTemplate template = BeanUtils.getBean(SimpMessagingTemplate.class);
if (!notice.getUserNoticeType().equals(TypeConst.UserNotice.NEW_EST)) {
NoticeResponseDto responseDto = new NoticeResponseDto(userNotice);
responseDto.setRegisterDt(LocalDateTime.now());
template.convertAndSend("/api/socket/subscribe/" + notice.getUserId(), responseDto);
}
}
}
Entity Listener
에서는 생성자 주입이나 필드 주입을 통한 생성자 주입이 불가능하기 때문에 Bean을 받아올 수 있는 Util을 따로 생성해주어야 한다.
@Component
public class BeanUtils implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
BeanUtils.applicationContext = applicationContext;
}
public static <T> T getBean(Class<T> tClass) {
return applicationContext.getBean(tClass);
}
}
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@Builder
@Entity
@DynamicUpdate
@EntityListeners(NoticeListener.class)
public class Notice {