diff --git a/src/main/java/com/mybooks/batch/config/batch/birthdaycoupon/BirthDayCouponBatchConfig.java b/src/main/java/com/mybooks/batch/config/batch/birthdaycoupon/BirthDayCouponBatchConfig.java index bbe5a7c..f35c74d 100644 --- a/src/main/java/com/mybooks/batch/config/batch/birthdaycoupon/BirthDayCouponBatchConfig.java +++ b/src/main/java/com/mybooks/batch/config/batch/birthdaycoupon/BirthDayCouponBatchConfig.java @@ -52,10 +52,10 @@ public class BirthDayCouponBatchConfig { private final JobBuilderFactory jobBuilderFactory; private final StepBuilderFactory stepBuilderFactory; - public final SqlSessionFactory sqlSessionFactory; + private final SqlSessionFactory sqlSessionFactory; private final JobLauncher jobLauncher; private final CouponMapper couponMapper; - private static final int CHUNK_SIZE = 10; + private static final int CHUNK_SIZE = 10000; /** * methodName : runJob
@@ -69,7 +69,7 @@ public class BirthDayCouponBatchConfig { * 제공한 입력이 유요하지 않은 경우 발생 * @throws JobRestartException 작업을 다시 시작하려는 불법적인 시도를 나타내는 예외 */ - @Scheduled(cron = "0 30 23 L * *") + @Scheduled(cron = "0 30 23 L * *", zone = "Asia/Seoul") public void runJob() throws JobInstanceAlreadyCompleteException, JobExecutionAlreadyRunningException, JobParametersInvalidException, JobRestartException { diff --git a/src/main/java/com/mybooks/batch/config/batch/usergradechangebatchconfig/UserGradeChangeBatchConfig.java b/src/main/java/com/mybooks/batch/config/batch/usergradechangebatchconfig/UserGradeChangeBatchConfig.java new file mode 100644 index 0000000..d8c9cc1 --- /dev/null +++ b/src/main/java/com/mybooks/batch/config/batch/usergradechangebatchconfig/UserGradeChangeBatchConfig.java @@ -0,0 +1,161 @@ +package com.mybooks.batch.config.batch.usergradechangebatchconfig; + +import com.mybooks.batch.useractualpayment.model.UserActualPayment; +import com.mybooks.batch.useractualpayment.model.UserGrade; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import lombok.RequiredArgsConstructor; +import org.apache.ibatis.session.SqlSessionFactory; +import org.mybatis.spring.batch.MyBatisBatchItemWriter; +import org.mybatis.spring.batch.MyBatisPagingItemReader; +import org.mybatis.spring.batch.builder.MyBatisBatchItemWriterBuilder; +import org.mybatis.spring.batch.builder.MyBatisPagingItemReaderBuilder; +import org.springframework.batch.core.Job; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.JobParametersBuilder; +import org.springframework.batch.core.JobParametersInvalidException; +import org.springframework.batch.core.Step; +import org.springframework.batch.core.configuration.annotation.JobBuilderFactory; +import org.springframework.batch.core.configuration.annotation.JobScope; +import org.springframework.batch.core.configuration.annotation.StepBuilderFactory; +import org.springframework.batch.core.configuration.annotation.StepScope; +import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException; +import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException; +import org.springframework.batch.core.repository.JobRestartException; +import org.springframework.batch.item.ItemProcessor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.Scheduled; + +/** + * packageName : com.mybooks.batch.config.batch.usergradechangebatchconfig + * fileName : UserGradeChangeBatchConfig + * author : damho-lee + * date : 3/21/24 + * description : + * =========================================================== + * DATE AUTHOR NOTE + * ----------------------------------------------------------- + * 3/21/24 damho-lee 최초 생성 + */ +@Configuration +@RequiredArgsConstructor +public class UserGradeChangeBatchConfig { + private final JobBuilderFactory jobBuilderFactory; + private final StepBuilderFactory stepBuilderFactory; + private final SqlSessionFactory sqlSessionFactory; + private final JobLauncher jobLauncher; + private static final int CHUNK_SIZE = 10000; + + /** + * methodName : runJob
+ * author : damho-lee
+ * description : 최근 3개월의 실결제금액에 따라 회원 등급 조회해서 회원등급 변경하는 Job 을 실행시키는 메서드. 3개월에 한 번 1일 오전 1시에 실행
+ * + * @throws JobInstanceAlreadyCompleteException Job 이 이미 완료되어 실행시킬 Job 이 없다 -> JobParameter 가 다르면 다른 Job 으로 인식한다 + * @throws JobExecutionAlreadyRunningException Job 이 이미 실행중이다 -> 스프링 배치가 DB 의 테이블을 참조하는데 배치 프로그램이 + * 비정상적으로 종료되는 경우 DB 테이블에 완료되었다고 작성하지 못하기 때문에 발생 + * @throws JobParametersInvalidException JobParameter 가 유요하지 않다 -> 필요한 Parameter 가 제공되지 않거나 + * 제공한 입력이 유요하지 않은 경우 발생 + * @throws JobRestartException 작업을 다시 시작하려는 불법적인 시도를 나타내는 예외 + */ + @Scheduled(cron = "0 0 1 1 */3 *", zone = "Asia/Seoul") + public void runJob() throws JobInstanceAlreadyCompleteException, JobExecutionAlreadyRunningException, + JobParametersInvalidException, JobRestartException { + + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd:HH:mm:ss"); + String formattedDateTime = LocalDateTime.now().format(formatter); + + JobParameters parameters = new JobParametersBuilder() + .addString("requestDate", formattedDateTime) + .toJobParameters(); + jobLauncher.run(userGradeChangeJob(), parameters); + } + + /** + * methodName : userGradeChangeJob
+ * author : damho-lee
+ * description : 회원 등급 변경 Job.
+ * + * @return job + */ + @Bean + public Job userGradeChangeJob() { + return jobBuilderFactory.get("changeUserGradeJob") + .start(changeUserGradeStep(null)) + .build(); + } + + /** + * methodName : changeUserGradeStep
+ * author : damho-lee
+ * description : 회원 등급 변경하는 Step.
+ * + * @param requestDate String + * @return step + */ + @Bean + @JobScope + public Step changeUserGradeStep(@Value("#{jobParameters['requestDate']}") String requestDate) { + return stepBuilderFactory.get("changeUserGradeStep") + .chunk(CHUNK_SIZE) + .reader(userActualPaymentReader(null)) + .processor(userActualPaymentProcessor(null)) + .writer(updateUserGradeWriter(null)) + .build(); + } + + /** + * methodName : userActualPaymentReader
+ * author : damho-lee
+ * description : userId 와 최근 3개월의 실결제금액으로 어느 등급에 해당하는지(userGradeId)를 조회하는 reader.
+ * + * @param requestDate String + * @return MyBatisPagingItemReader + */ + @Bean + @StepScope + public MyBatisPagingItemReader userActualPaymentReader( + @Value("#{jobParameters['requestDate']}") String requestDate) { + return new MyBatisPagingItemReaderBuilder() + .pageSize(CHUNK_SIZE) + .sqlSessionFactory(sqlSessionFactory) + .queryId("com.mybooks.batch.useractualpayment.mapper.UserActualPaymentMapper.getUserActualPayment") + .build(); + } + + /** + * methodName : userActualPaymentProcessor
+ * author : damho-lee
+ * description : 회원 아이디, 실결제금액, 회원 등급 아이디 -> 회원 아이디, 회원 등급 아이디로 변환하는 processor.
+ * + * @param requestDate String + * @return ItemProcessor + */ + @Bean + @StepScope + public ItemProcessor userActualPaymentProcessor( + @Value("#{jobParameters['requestDate']}") String requestDate) { + return userActualPayment -> new UserGrade(userActualPayment.getUserId(), userActualPayment.getUserGradeId()); + } + + /** + * methodName : updateUserGradeWriter
+ * author : damho-lee
+ * description : 회원 등급 변경하는 writer. 회원등급 변경일자는 현재시간으로.
+ * + * @param requestDate String + * @return MyBatisBatchItemWriter + */ + @Bean + @StepScope + public MyBatisBatchItemWriter updateUserGradeWriter( + @Value("#{jobParameters['requestDate']}") String requestDate) { + return new MyBatisBatchItemWriterBuilder() + .sqlSessionFactory(sqlSessionFactory) + .statementId("com.mybooks.batch.useractualpayment.mapper.UserActualPaymentMapper.updateUserGrade") + .build(); + } +} \ No newline at end of file diff --git a/src/main/java/com/mybooks/batch/config/batch/userstatuschange/UserStatusChangeBatchConfig.java b/src/main/java/com/mybooks/batch/config/batch/userstatuschange/UserStatusChangeBatchConfig.java index 6f80e6a..a704c4c 100644 --- a/src/main/java/com/mybooks/batch/config/batch/userstatuschange/UserStatusChangeBatchConfig.java +++ b/src/main/java/com/mybooks/batch/config/batch/userstatuschange/UserStatusChangeBatchConfig.java @@ -46,9 +46,9 @@ public class UserStatusChangeBatchConfig { private final JobBuilderFactory jobBuilderFactory; private final StepBuilderFactory stepBuilderFactory; - public final SqlSessionFactory sqlSessionFactory; + private final SqlSessionFactory sqlSessionFactory; private final JobLauncher jobLauncher; - private static final int CHUNK_SIZE = 10; + private static final int CHUNK_SIZE = 10000; /** * methodName : runJob
@@ -62,7 +62,7 @@ public class UserStatusChangeBatchConfig { * 제공한 입력이 유효하지 않은 경우 발생 * @throws JobRestartException 작업을 다시 시작하려는 시도를 나타내는 예외 */ - @Scheduled(cron = "0 0 0 * * *") + @Scheduled(cron = "0 0 0 * * *", zone = "Asia/Seoul") public void runJob() throws JobInstanceAlreadyCompleteException, JobExecutionAlreadyRunningException, JobParametersInvalidException, JobRestartException { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd:HH:mm:ss"); diff --git a/src/main/java/com/mybooks/batch/useractualpayment/mapper/UserActualPaymentMapper.java b/src/main/java/com/mybooks/batch/useractualpayment/mapper/UserActualPaymentMapper.java new file mode 100644 index 0000000..78d6bbf --- /dev/null +++ b/src/main/java/com/mybooks/batch/useractualpayment/mapper/UserActualPaymentMapper.java @@ -0,0 +1,23 @@ +package com.mybooks.batch.useractualpayment.mapper; + +import com.mybooks.batch.useractualpayment.model.UserActualPayment; +import com.mybooks.batch.useractualpayment.model.UserGrade; +import org.apache.ibatis.annotations.Mapper; + +/** + * packageName : com.mybooks.batch.useractualpayment.mapper + * fileName : UserActualPaymentMapper + * author : damho-lee + * date : 3/21/24 + * description : + * =========================================================== + * DATE AUTHOR NOTE + * ----------------------------------------------------------- + * 3/21/24 damho-lee 최초 생성 + */ +@Mapper +public interface UserActualPaymentMapper { + UserActualPayment getUserActualPayment(); + + void updateUserGrade(UserGrade userGrade); +} diff --git a/src/main/java/com/mybooks/batch/useractualpayment/model/UserActualPayment.java b/src/main/java/com/mybooks/batch/useractualpayment/model/UserActualPayment.java new file mode 100644 index 0000000..5d26535 --- /dev/null +++ b/src/main/java/com/mybooks/batch/useractualpayment/model/UserActualPayment.java @@ -0,0 +1,23 @@ +package com.mybooks.batch.useractualpayment.model; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * packageName : com.mybooks.batch.order.model + * fileName : Order + * author : damho-lee + * date : 3/20/24 + * description : + * =========================================================== + * DATE AUTHOR NOTE + * ----------------------------------------------------------- + * 3/20/24 damho-lee 최초 생성 + */ +@Getter +@AllArgsConstructor +public class UserActualPayment { + private Long userId; + private Integer actualPayment; + private Integer userGradeId; +} diff --git a/src/main/java/com/mybooks/batch/useractualpayment/model/UserGrade.java b/src/main/java/com/mybooks/batch/useractualpayment/model/UserGrade.java new file mode 100644 index 0000000..6b1e06e --- /dev/null +++ b/src/main/java/com/mybooks/batch/useractualpayment/model/UserGrade.java @@ -0,0 +1,22 @@ +package com.mybooks.batch.useractualpayment.model; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * packageName : com.mybooks.batch.useractualpayment.model + * fileName : UserGrade + * author : damho-lee + * date : 3/21/24 + * description : + * =========================================================== + * DATE AUTHOR NOTE + * ----------------------------------------------------------- + * 3/21/24 damho-lee 최초 생성 + */ +@Getter +@AllArgsConstructor +public class UserGrade { + private Long userId; + private Integer userGradeId; +} diff --git a/src/main/resources/application-dev.properties b/src/main/resources/application-dev.properties new file mode 100644 index 0000000..fa71b44 --- /dev/null +++ b/src/main/resources/application-dev.properties @@ -0,0 +1 @@ +database.mysql.url=65b73eab47984c8b9b70241c698406cd \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 0e31f00..7b9a4ab 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -6,7 +6,6 @@ key.manager.path=/keymanager/v1.0/appkey/{app-key}/secrets/{key-id} key.manager.app-key=CuKPvJQR7enquqrZ key.manager.password=mybooks ## mysql -database.mysql.url=65b73eab47984c8b9b70241c698406cd database.mysql.userName=901b405fe80d4c00b14bc099a72a33ad database.mysql.password=cda93b8395b641bfbe9a967cd60fdd49 database.mysql.initialSize=10 @@ -17,4 +16,7 @@ database.mysql.maxWait=1000 spring.application.name=batch-service #mybatis spring.batch.jdbc.initialize-schema=always -mybatis.executor-type=batch \ No newline at end of file +mybatis.executor-type=batch +## +#spring.profiles.active=dev +database.mysql.url=9053ef8fd6e04a87aab73321a565c1b2 \ No newline at end of file diff --git a/src/main/resources/mapper/mybatis-useractualpaymentmapper.xml b/src/main/resources/mapper/mybatis-useractualpaymentmapper.xml new file mode 100644 index 0000000..1c447ff --- /dev/null +++ b/src/main/resources/mapper/mybatis-useractualpaymentmapper.xml @@ -0,0 +1,47 @@ + + + + + + + UPDATE user + SET user_grade_id = #{userGradeId}, + user_grade_changed_date = CURRENT_DATE + WHERE user_id = #{userId} + + \ No newline at end of file