Entity Listener

2021-08-23
  • Java
  • JPA

Entity Listener

정의

1

hibernate 공식 문서

Entity Life Cycle (Persist, Remove, Update, Load) 에 대한 이벤트 발생 시 call back 처리

메서드

2

Pre- vs Post-

@PreUpdate callback is only called if the data is actually changed

즉 @PreUpdate는 실질적으로 Update SQL문이 실행될 때 동작한다. (트랜잭션 종료 or flush 하는 시점)

트랜잭션 바운더리 안에서 실행되기 때문에 영속성 컨텍스트에 의해 관리됨

@PreUpdate가 동작할 때 DB에서 변경되는 값을 조회할지라도, 이미 변경된 값으로 조회가 되기 때문에 결과적으로 행위 자체는 @PostUpdate와 동일한 결과

실제 적용

사용 이유

  1. 알림를 보내주는 곳(저장 시점)이 산발적으로 흩어져있어서, 소켓을 전송하는 각 모듈 하나하나에 추가하는데 시간이 오래걸리고 반복적인 작업 → 생산성이 저하되며, 코드가 반복됨

  2. 현재의 요구사항 : 알림 객체가 Persist 되는 시점에 Socket으로 알림을 보내준다고 추상화할 수 있다.

    → 따라서, NoticeListener 생성하여 Socket 알림 전송을 처리한다.

Listener 객체 생성

@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);
        }
    }

}

BeanUtils?

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);
  }
}

Entity 적용

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@Builder
@Entity
@DynamicUpdate
@EntityListeners(NoticeListener.class)
public class Notice {
Profile picture

2yeseul

트리플에서 백엔드 개발을 맡고 있습니다. 무한 삽질을 기록합니다. ⚒️