@Entity
@EntityListeners(EntityListener.class)
class Entity
@Slf4j
public class EntityListener {
@PostPersist
public void postPersist(Entity entity) {
log.info("Auditing... " + entity.getId());
}
}
Repository
에 Operation
을 발생시키면,ConcurrenetModificationException
이 발생하게 됨EntityListener
에서는 Repository
를 호출하지 않아야 함을 명시하고 있음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();
}
}
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();
}
}