Trigger 발생 후 Job 의 execute 가 실행될 때

@Transactional
@Override
public void execute(JobExecutionContext context) throws JobExecutionException { //예약된 좌석이 결제 30분 후 아직 '입실 전' 상태 일 때 좌석 취소 시킴
    Long bookingId = context.getJobDetail().getJobDataMap().getLong("bookingId");
    Booking booking = bookingRepository.findByBookingId(bookingId);

    if (booking != null && booking.getSeat() != null && booking.getStatus().equals(BookingStatus.beforeEnteringRoom)) {
            booking.cancelBeforeEnteringSeat();
            booking.getSeat().updateSeatStatus(true); // 좌석 사용 가능으로 변경
    }

}
2024-07-23T04:52:17.049+09:00 ERROR 68 --- [QuartzThread--1] org.quartz.core.JobRunShell              : Job cancelBeforeEnteringSeatGroup.cancelBeforeEnteringSeatJob_22 threw an unhandled Exception: 

org.hibernate.LazyInitializationException: could not initialize proxy [com.example.catchStudyEx.domain.entity.Seat#22] - no Session
	at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:165) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
	at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:314) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
	at org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor.intercept(ByteBuddyInterceptor.java:44) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
	at org.hibernate.proxy.ProxyConfiguration$InterceptorDispatcher.intercept(ProxyConfiguration.java:102) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
	at com.example.catchStudyEx.domain.entity.Seat$HibernateProxy$KlEAiIgl.updateSeatStatus(Unknown Source) ~[main/:na]
	at com.example.catchStudyEx.global.Job.CancelBeforeEnteringSeatJob.execute(CancelBeforeEnteringSeatJob.java:37) ~[main/:na]
	at org.quartz.core.JobRunShell.run(JobRunShell.java:202) ~[quartz-2.3.2.jar:na]
	at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573) ~[quartz-2.3.2.jar:na]

2024-07-23T04:52:17.053+09:00 ERROR 68 --- [QuartzThread--1] org.quartz.core.ErrorLogger              : Job (cancelBeforeEnteringSeatGroup.cancelBeforeEnteringSeatJob_22 threw an exception.

org.quartz.SchedulerException: Job threw an unhandled exception.
	at org.quartz.core.JobRunShell.run(JobRunShell.java:213) ~[quartz-2.3.2.jar:na]
	at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573) ~[quartz-2.3.2.jar:na]
Caused by: org.hibernate.LazyInitializationException: could not initialize proxy [com.example.catchStudyEx.domain.entity.Seat#22] - no Session
	at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:165) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
	at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:314) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
	at org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor.intercept(ByteBuddyInterceptor.java:44) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
	at org.hibernate.proxy.ProxyConfiguration$InterceptorDispatcher.intercept(ProxyConfiguration.java:102) ~[hibernate-core-6.5.2.Final.jar:6.5.2.Final]
	at com.example.catchStudyEx.domain.entity.Seat$HibernateProxy$KlEAiIgl.updateSeatStatus(Unknown Source) ~[main/:na]
	at com.example.catchStudyEx.global.Job.CancelBeforeEnteringSeatJob.execute(CancelBeforeEnteringSeatJob.java:37) ~[main/:na]
	at org.quartz.core.JobRunShell.run(JobRunShell.java:202) ~[quartz-2.3.2.jar:na]
	... 1 common frames omitted

Caused by: org.hibernate.LazyInitializationException: could not initialize proxy [com.example.catchStudyEx.domain.entity.Seat#22] - no Session

@Transactioanl
@Override
public void execute(JobExecutionContext context) throws JobExecutionException { //예약된 좌석이 결제 30분 후 아직 '입실 전' 상태 일 때 좌석 취소 시킴
    printInfo();
    Long bookingId = context.getJobDetail().getJobDataMap().getLong("bookingId");
    Booking booking = bookingRepository.findByBookingId(bookingId);

    if (booking != null && booking.getSeat() != null && booking.getStatus().equals(BookingStatus.beforeEnteringRoom)) {
        Seat seat = seatRepository.findBySeatId(booking.getSeat().getSeatId()).orElse(null);    
        booking.cancelBeforeEnteringSeat();
        seat.updateSeatStatus(true); // 좌석 사용 가능으로 변경
    }
}

private void printInfo(){
        boolean txActive = TransactionSynchronizationManager.isActualTransactionActive();
        log.info("tx active={}",txActive );
}

LazyInitializationException 는 없어졌지만 tx active = false, @Transactional 적용이 안됨.

찾아보니 스프링부트 애플리케이션에서 분리되어 나간 작업 클래스 모듈에서는 @Transactional을 일반적인 경우처럼 쉽게 사용할 수 없고 Quartz 스케줄러가 기본적으로 Spring의 트랜잭션 관리 기능과 완벽하게 통합되지 않기 때문에 생기는 문제

@Autowired
private TransactionTemplate transactionTemplate;

@Override
public void execute(JobExecutionContext context) throws JobExecutionException { //예약된 좌석이 결제 30분 후 아직 '입실 전' 상태 일 때 좌석 취소 시킴
    Long bookingId = context.getJobDetail().getJobDataMap().getLong("bookingId");

    try{
        transactionTemplate.execute(status -> {
            Booking booking = bookingRepository.findByBookingId(bookingId);

            if (booking != null && booking.getSeat() != null && booking.getStatus().equals(BookingStatus.beforeEnteringRoom)) {
                Seat seat = seatRepository.findBySeatId(booking.getSeat().getSeatId()).orElse(null);
                if(seat != null){
                    booking.cancelBeforeEnteringSeat();
                    seat.updateSeatStatus(true); // 좌석 사용 가능으로 변경
                }

            }
            return null;

        });

    }catch (Exception e){
        log.error("Job execution resulted in exception: ", e);
        throw new JobExecutionException(e);
    }
}