본문 바로가기

JAVA/JAVA-Project

[스프링] 좌석 만료일이 지났을 때 처리 21. 05. 24.

개요

   팀 프로젝트로 독서실 관리 프로그램을 만들고 있다. 좌석은 등록일과 만료일이 있고, 만료일이 지나면 좌석 상태를 '빈 좌석'으로 만들어야 한다.
Quartz 라이브러리로 스케줄러를 구성해서 처리해 보았다.

 

초기 설정

pom.xml에 라이브러리 추가.

<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz</artifactId>
    <version>2.3.2</version>
</dependency>

<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz-jobs</artifactId>
    <version>2.3.2</version>
</dependency>

 

 

root-context.xml 네임스페이스에 task를 체크한 후

<task:annotation-driven/>

추가.

 

PeriodCheckTask.java

package xyz.sumtplus.task;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j;
import xyz.sumtplus.domain.LockerVO;
import xyz.sumtplus.domain.RegInfoVO;
import xyz.sumtplus.domain.SeatVO;
import xyz.sumtplus.mapper.LockerMapper;
import xyz.sumtplus.mapper.RegInfoMapper;
import xyz.sumtplus.mapper.SeatMapper;

@Log4j
@Component
@AllArgsConstructor
public class PeriodCheckTask {

    private RegInfoMapper regInfoMapper;
    private SeatMapper seatMapper;
    private LockerMapper lockerMapper;

    @Transactional
    @Scheduled(cron="0 30 23 * * *")
    public void checkPeriod() throws Exception {

        log.warn("테스크 실행...");
        log.warn("========================================");
        List<RegInfoVO> regList = regInfoMapper.getExpireInfo();
        if(regList.size() == 0) return;

        regList.forEach(log::info);
        for(RegInfoVO vo: regList) {
            SeatVO seatVO = new SeatVO();
            seatVO.setSno(vo.getSeatNo());
            seatVO.setStatus(false);
            seatVO.setUserNo(0L);

            if(vo.getLockerNo() != null) {    
                LockerVO lockerVO = new LockerVO();
                lockerVO.setLno(vo.getLockerNo());
                lockerVO.setStatus(false);
                lockerVO.setUserNo(0L);
                lockerMapper.updateStatus(lockerVO);
                log.warn(lockerVO);
            }
            seatMapper.updateStatus(seatVO);
            log.warn(seatVO);
        }
        log.warn("========================================");
        log.warn(regInfoMapper.deleteRegInfo());
    }
}

 

🔶 @scheduled를 이용해서 매일 23시 30분에 실행되도록 했다.
🔶 만료된 이용 등록 정보 리스트를 불러와서 for문으로 순회했다.
🔶 만료된 이용 등록 정보에서 좌석번호(seatNo)와 사물함 번호(lockerNo)을 알아야 정보가 삭제 되면서 좌석과 사물함 이용상태도 변경할 수 있기 때문에!
🔶 항상 Null 처리도 해야 한다.

 

ReginfoMapper.xml 일부

<!-- 만료된 이용 등록 정보 조회 -->    
<select id="getExpireInfo" resultType="xyz.sumtplus.domain.RegInfoVO">
    SELECT * FROM TBL_REGINFO
    <![CDATA[WHERE ENDDATE < TO_DATE(SYSDATE-1, 'YY/MM/DD')]]>
</select>

<!-- 만료일 지난 정보 삭제 -->
<delete id="deleteRegInfo">
    DELETE TBL_REGINFO
    WHERE REGNO IN
        (SELECT REGNO
        FROM
            (SELECT * FROM TBL_REGINFO
            <![CDATA[WHERE ENDDATE < TO_DATE(SYSDATE-1, 'YY/MM/DD')))]]>
</delete>

 

🔶 CDATA는 꺽쇠 때문에 필수로 써줘야 함.
🔶 등록번호를 조건으로 지워야 해서 서브쿼리를 이용했는데, 서브쿼리의 결과 행이 두 개 이상 나올 수 있다. (여러 명이 같은 날 만료 되는 경우)
🔶 단순히 WHERE 절에서 REGNO = 으로 하면 결과 행이 하나여야 하기 때문에 IN 연산자를 사용해야 한다!