JPA ENTITY LISTENER

0️⃣1️⃣·2024년 3월 2일
0

개발

목록 보기
6/7
post-custom-banner

EntityListener

  • JPA의 Entity에서 발생하는 변화들을 인지하기 위한 역할로서 사용되는 클래스
  • Entity와 관련된 트랜잭션(라이프사이클)에 관여하여 감사(Audit)하기 위한 용도로 사용될 수 있음
@Entity
@EntityListeners(EntityListener.class)
class Entity

Implementation

  • @PostPersist, @PostRemove, @PostUpdate의 형태로 사용할 수 있음
  • JPA의 엔티티 라이프사이클과 관련된 행동들을 정의할 수 있음
@Slf4j
public class EntityListener {    
    @PostPersist
    public void postPersist(Entity entity) {
    	log.info("Auditing... " + entity.getId());
    }
}

Autowired

In general, the lifecycle method of a portable application should not invoke EntityManager or query operations, access other entity instances, or modify relationships within the same persistence context[44][45]. A lifecycle callback method may modify the non-relationship state of the entity on which it is invoked.

public class EntityListener {
	private static AnotherEntityRepository anotherEntityRepository;

	@Autowired
    public void init(AnotherEntityRepository anotherEntityRepository) {
    	this.anotherEntityRepository = anotherEntityRepository;
    }
    
    @PostPersist
    public void postPersist(Entity entity) {
    	anotherEntityRepository.countAll();
    }
}

Event Programming

  • EntityListener에서 추가적인 작업이 필요하면, 이벤트 프로그래밍을 통해서 작업할 수 있음
@Component
public class WithdrawAccountSnapshotEntityListener {
    private static ApplicationEventPublisher applicationEventPublisher;

    @Autowired
    public void init(ApplicationEventPublisher applicationEventPublisher) {
        this.applicationEventPublisher = applicationEventPublisher;
    }

    @PostPersist
    public void onPostPersist(Entity entity) {
        applicationEventPublisher.publishEvent(new CustomEvent(entity.getId()));
    }
}
  • 이벤트 핸들러를 통해서, 트랜잭션을 분리하고 비동기적으로 이벤트를 처리하도록 작성할 수 있음
  • EntityListener에서는 메시지 발행에 대한 역할만 부여하고 이벤트 프로그래밍을 통해서 추가 로직에 대해서 구현
  • 이벤트 핸들 로직에서는 도메인 로직을 포함하면 안된다. 포함하면, 도메인 로직이 여기저기 분산되는 문제가 발생할 수 있음
  • 이벤트 핸들 로직에서는 기존 도메인에 영향을 주지 않는 코드들에 대해서만 작성하는 것이 좋아보임
    • 다른 시스템으로 노티 메시지 전송
@Component
@RequiredArgsConstructor
@Slf4j
public class EntityEventHandler {
    private final AnotherEntityRepository anotherEntityRepository;
    private final MessageQueue messagequeue;

    @Async
    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT, classes = CustomEvent.class, fallbackExecution = true)
    @Transactional
	public void handle(CustomEvent customEvent) {
    	anotherEntityRepository.countAll();
    }
}

post-custom-banner

0개의 댓글