📚
TIL
  • README
  • Git
    • Basic
    • Remote Repository
    • Log & Diff
    • Rebase&Cherri-Pick
    • git-flow
  • DevOps
    • Monolithic vs MSA
    • Jenkins 시작하기
    • Airflow 시작하기
    • Airflow 시작하기
    • Build Tools
      • maven
  • 개발 방법론
    • TDD
  • Spring
    • IoC
    • Is Spring Bean Thread-Safe?
    • Spring Singleton
    • Component Scan
    • Spring Annotation
    • 의존 관계 주입(DI)
    • Lombok 활용하기
    • Bean 생명주기와 콜백
    • Bean Scope
    • AOP(1) - AOP란
    • AOP(2) - Aop Proxy
    • AOP(3) - Dynamic Proxy
    • AOP(4) - AspectJ
    • POJO
    • Spring 서비스 구조
    • Transaction
    • JPA란?
    • JPA Entity
    • Spring Data JPA
    • Spring Data Specification
    • Model Mapping
    • Cache
    • restTemplate
    • YAML 파일 설정
    • Spring Boot
      • H2 DB 설정
      • 다중 데이터베이스 설정
      • Mybatis 연동하기
    • Spring Batch
      • Batch 시작해보기
      • Batch Job Flow
      • Job
      • Step
      • Batch Scope & Job Parameter
      • JobRepository와 메타테이블
      • Chunk 지향 프로그래밍
      • ItemReader
      • ItemProcessor
      • ItemWriter
      • Batch Schedular
      • Job별 Bean등록하기
      • Batch 구현시 발생한 오류 정리
      • Spring Batch Scaling
        • Multithread Job구현시 이슈사항
    • Spring test
      • Junit5
        • 테스트 이름 표기
        • 테스트 그룹 사이의 관계
        • 태그와 필터링
        • 동적 테스트
        • 테스트 LifeCycle
        • 테스트 메서드
        • 테스트 순서
        • AssertJ
        • 테스트 병렬 실행
        • AssertJ
        • Mock
      • Spring Boot Test DB 분리
      • Spring Batch Test
  • Web Application
    • Web Server & WAS
    • 관련 개념 - HTTP API, HTML, CSR, SSR
    • Servlet
    • JSP
    • Cookie And Session
    • 예외페이지
    • Java Bean
    • JDBC
    • Connection Pool
    • 파일 업로드
    • Expression Language
    • JSTL
    • FrontController패턴 Command 패턴
    • Forwarding
    • MVC
    • 회원가입예제
    • 참고
      • 개발환경설정
  • Java+
    • SOAP/WSDL vs REST
    • WSDL을 JAVA로 변환하기
    • SOAP 통신 OPEN API로 개발해보기
  • Java
    • Basic
      • 변수와 타입
      • 연산자
      • 조건문과 반복문
      • 참조 타입
      • 클래스
      • 상속(Inheritance)
      • 인터페이스(Interface)
      • 중첩 클래스와 중첩 인터페이스
      • 예외 처리
      • API - Object, System, Class, Math, Wrapper
      • API - String, StringBuffer, StringBuilder
      • Thread
      • Generic
      • Lambda
      • Collection - List, Set
      • Collection - Map
      • Collection - Tree
      • Collection - Stack, Queue
      • Stream
      • Reflection
      • 정규표현식
      • GUI
      • UML
      • Serializable
    • Advanced
      • OutOfMemoryError
      • AutoValue
      • meta-annotation
        • @Retention
        • @Target
        • @Repeatable
    • Effective Java 3/E
      • ITEM 1: Static Factory Method(정적 메소드)
      • ITEM 2: Builder Pattern
      • ITEM 3: Singleton
      • ITEM 4: Private Constructor
      • ITEM 5: Dependency Injection
      • ITEM 6: Avoid Unnecessary Object
      • ITEM 7: Eliminate Object Reference
      • ITEM 8: Avoid finalizer and cleaner
      • ITEM 9: try-with-resources
      • ITEM 10: The gerneral contract when overriding equlas
      • ITEM 11: Overriding hashCode
      • ITEM 12: overriding toString
      • ITEM 13: overriding clone judiciously
      • ITEM 14: Consider implementing comparable
      • ITEM 15: 클래스와 멤버의 접근을 최소화해라
      • ITEM 16: Use Accessor methods
      • ITEM 17: 변경 가능성을 최소화해라(불변 클래스)
      • ITEM 18: 상속보단 컴포지션을 사용해라
      • ITEM 19: 상속을 고려해 설계하고 문서화해라
      • ITEM 20: 추상 클래스보다 인터페이스를 우선하라
      • ITEM 21: 인터페이스는 구현하는 쪽을 생각해 설계해라.
      • ITEM 22: 인터페이스는 타입을 정의하는 용도로만 사용해라
      • ITEM 23: 태그 달린 클래스보다 클래스 계층구조를 활용해라
      • ITEM 24: 멤버 클래스는 되도록 static으로 구현해라
      • ITEM 25: 톱레벨 클래스는 한 파일에 하나만 생성해라.
      • ITEM 26: Raw type은 사용하지 마라
      • ITEM 27: 비검사 경고를 제거해라
      • ITEM 28: 배열보다는 리스트를 사용해라
      • ITEM 29: 이왕이면 제네릭 타입으로 만들어라
      • ITEM 30: 이왕이면 제네릭 메서드로 만들어라
      • ITEM 31 : 한정적 와일드카드를 사용해 API 유연성을 높여라
      • ITEM 32: 제네릭과 가변인수를 함께 쓸 때는 신중해라
      • ITEM 33: 타입 안전 이종 컨테이너를 고려해라
      • ITEM 34: int 상수 대신 열거 타입을 사용해라
      • ITEM 35: ordinal 메서드 대신 인스턴스 필드를 사용해라
      • ITEM 36: 비트 필드 대신 EnumSet을 사용해라
      • ITEM 37: ordinal 인덱싱 대신 EnumMap을 사용해라
      • TEM 38 : 확장할 수 있는 열거타입이 필요하면 인터페이스를 사용해라
      • ITEM 39: 명명 패턴보다 애너테이션을 사용해라
      • ITEM 40: @Override 어노테이션을 일관되게 사용해라
      • ITEM 41: 정의하려는 것이 타입이라면 마커 인터페이스를 사용해라
      • ITEM 42: 익명 클래스보다는 람다를 사용해라
      • ITEM 43: 람다보다는 메서드 참조를 사용해라
      • ITEM 44: 표준 함수형 인터페이스를 사용해라
      • ITEM 45: 스트림은 주의해서 사용해라
      • ITEM 46: 스트림에서 부작용 없는 함수를 사용해라
      • ITEM 47: 반환 타입으로는 스트림보다 컬렉션이 낫다.
      • ITEM 48: 스트림 병렬화는 주의해서 사용해라
      • ITEM 49: 매개변수가 유효한지 검사해라
      • ITEM 50: 적시에 방어적 복사본을 만들어라
      • ITEM 51: 메서드 시그니처를 신중히 설계해라
      • ITEM 52: 다중정의는 신중히 사용해라
      • ITEM 53: 가변인수는 신중히 사용해라
      • ITEM 54: null이 아닌, 빈 컬렉션이나 배열을 반환해라
      • ITEM 55: Optional 반환은 신중하게 해라
      • ITEM 56: 공개된 API 요소에는 항상 주석을 작성해라
      • ITEM 57: 지역변수의 범위를 최소화해라
      • ITEM 58: 전통적인 for 문보다는 for-each문을 사용해라
      • ITEM 59: 라이브러리를 익히고 사용해라
      • ITEM 60: 정확한 답이 필요하다면 float와 double은 피해라
      • ITEM 61: 박싱된 기본 타입보다는 기본 타입을 사용해라
      • ITEM 62: 다른 타입이 적절하다면 문자열 사용을 피해라
      • ITEM 63: 문자열 연결은 느리니 주의해라
      • ITEM 64: 객체는 인터페이스를 사용해 참조해라
      • ITEM 65: 리플렉션보다는 인터페이스를 사용해라
      • ITEM 66: 네이티브 메서드는 신중히 사용해라
      • ITEM 67: 최적화는 신중히 해라
      • ITEM 68: 일반적으로 통용되는 명명 규칙을 따라라
    • 객체지향 설계 원칙(SOLID)
    • 디자인패턴
      • Strategy Pattern
      • Template Method Pattern
      • Factory Method Pattern
      • Singleton
      • Delegation
      • Proxy
      • Adapter Pattern
    • 실습
      • 인터페이스 실습 - Vehicle
      • 인터페이스 실습 - Remote
      • GUI 실습 - Calculator
      • GUI 실습 - button
      • GUI 실습 - lotto
      • Thread 실습 - 좌석예약, 메세지보내기
    • Jar vs War
  • 데이터베이스
    • KEY
    • Index
    • Transaction
    • Trigger
    • Procedure / Function
    • Package
    • 데이터베이스 배움터
      • 데이터베이스 시스템
      • 관계데이터 모델
      • 관계대수와 SQL
    • MySQL
      • Database란
      • MySQL 시작하기
      • MySQL Database
      • MySQL Table
      • CRUD
      • 관계형 데이터베이스
      • Server와 Client
    • PostgreSQL
    • NoSQL
      • Install Cassandra on mac
      • Cassandra란?
      • NiFi란
  • Algorithm
    • String
    • Recursion
    • Dynamic Programming
    • Array, Struct, Pointer
    • Math
    • Sort
    • List
    • Stack
    • Queue
    • Graph
    • Tree
    • Maze
    • AVL
    • 이진탐색트리(Binary Search Tree)
    • DFS와 BFS
    • 다익스트라 알고리즘(Dijkstra's Algorithm)
    • Red-Black 트리
    • A* 알고리즘
    • Heap
    • Huffman Coding
    • Priority Queue
    • Bellman-Ford 알고리즘
    • C++
      • Class
      • STL
        • STL pair
        • STL Container - Associate Container
        • STL Container - Sequence Container
        • STL Container - Container Adapter
  • JavaScript
    • JABASCRIPT BASIC
    • Shallow Copy vs Deep Copy
    • OBJECT MODEL
    • NODE
    • 동기 처리 vs 비동기 처리
    • AJAX
    • CALLBACK
    • PROMISE
    • DEFERRER
    • UNDERSCORE
    • WEBPACK
    • SCOPE
    • EXECUTION CONTEXT
    • Image Object
    • BFCache란?
    • history.scrollRestoration
    • Intersection Observer
    • JWT - JSON Web Token
    • HTML vs JSON
  • Vue.js
    • 환경설정
    • Vue.js란?
    • Vue Instance
    • Vue Component
    • Vue Router
    • HTTP 통신
    • Template
    • Single File Component
    • Vue Animation
    • Vuex
    • Djnago와 연동하기
  • Backbone.js
    • Model
    • Collection
    • Sync
    • view
  • Node.js
    • Doit! - 노드로 만들 수 있는 대표적인 서버와 용도
    • Doit! - 노드에 대해 알아보고 개발 도구 설치하기
    • Doit! - 노드 간단하게 살펴보기
    • Doit! - 노드의 자바스크립트와 친해지기
    • Doit! - 노드의 기본 기능 알아보기
    • Doit! - 웹 서버 만들기
    • Doit! - 데이터베이스 사용하기
    • Doit! - 익스프레스 프로젝트를 모듈화하기
    • Doit! - 뷰 템플릿 적용하기
    • Doit! - 패스포트로 사용자 인증하기
    • Doit! - 채팅서버 만들기
    • Doit! - JSON-RPC 서버 만들기
  • Python
    • Warning-Could not import the lzma module
    • Pandas
      • Pandas 자료구조
      • Pandas 데이터 입출력
      • DataFrame Data 살펴보기
      • 시각화 도구 - Matplotlib
  • ML
    • 추천 시스템
      • Collaborative Filtering
      • Matrix Factorization
  • Django
    • Basic
      • 환경설정
      • About Django
      • Start Django Project
      • Secret Key 관리하기
      • Settings 분리하기
      • Django App
      • Django View & URL (1)
      • Django Model
        • MySQL 연동
      • Django Admin
      • Django View & URL (2)
      • Django Template
      • Django Template & View & URL
      • Django Static
      • Django form
    • Advanced
      • Django Generic View
      • Django Automated Testing
      • Django Extenstion Template
      • Django Model Package
      • Django OpenSSL setting
    • REST framework
      • Rest API
      • Serializers
      • ViewSet
    • Error
      • 환경설정 zlib 오류발생
      • ModuleNotFoundError
    • 패키지
      • django-debug-toolbar
    • Vue.js 연동하기
  • Ruby
    • variable & input/output
    • 조건문
    • 반복문
    • Array & Hash
    • Method
    • Proc&Lamda
    • Class
  • Ruby on Rails
    • Scaffolding
    • Controller
    • Model
    • Model-M:N relation
    • Model Validation
    • 멋사 10주차 수업(Tip)
  • HTML/CSS
    • Udacity - Intro to HTML/CSS
    • Udacity - Responsive Web Design
    • Udacity - Responsive Images
    • HTML Basic
    • CSS Basic
    • HTML5 Sementic Tag
    • HTML 텍스트 관련 태그들
    • HTML5 멀티미디어
    • HTML 폼 관련 태그들
    • 텍스트 관련 스타일
    • 색상과 배경을 위한 스타일
    • 레이아웃을 위한 스타일
    • CSS 포지셔닝
    • 다재다능한 CSS3 선택자
    • CSS와 애니메이션
    • 반응형 웹이란?
  • OS(운영체제)
    • Linux
      • Daemon
      • Cron
      • 프로세스 관련 명령어
      • 텍스트 파일 명령어
  • Network
    • 네트워크 기본 개념
    • 네트워크 기본 규칙
    • 물리 계층
    • 데이터 링크 계층
    • 네트워크 계층
    • 전송 계층
    • 응용 계층
    • 네트워크 전체 흐름
    • 무선 랜
  • IT 기타지식
    • NAS란
Powered by GitBook
On this page
  • JobRepository
  • 배치 메타테이블 알아보기
  • 인메모리 JobRepository
  • Batch Infrastructure
  • BatchConfigurer
  • 참고

Was this helpful?

  1. Spring
  2. Spring Batch

JobRepository와 메타테이블

PreviousBatch Scope & Job ParameterNextChunk 지향 프로그래밍

Last updated 3 years ago

Was this helpful?

JobRepository

  • org.springframework.batch.core.repository.JobRepository ( 인터페이스 )

JobRepository는 배치 처리 정보를 담고 있는 *매커니즘이다.

  • 배치 수행과 관련된 수치 데이터(시작/종료 시간, 상태, 읽기/쓰기 횟수)

  • Job의 상태 유지 관리

  • RDBMS(관계형 데이터베이스)/인메로리 저장소를 사용

  • 배치 내 대부분 주요 컴포넌트가 공유

예를 들어, Job 한개가 실행되면 JobRepository에서 배치 실행에 관련된 정보를 담고 있는 도메인 JobExcution을 생성하며, Step의 실행정보를 담고 있는 StepExecution도 저장소에 저장해 전체 메타데이터를 저장/관리하는 역할을 수행한다.

  1. Job 실행하면 Job은 각 Step실행

  2. 각 Step이 실행되면 JobRepository 현재 상태로 갱신

즉, 실행된 Step, 현재 상태, 읽은 아이템 및 처리된 아이템 수 등이 모두 저장된다.

*매커니즘 : 어떠한 사물의 구조, 또는 그것이 작동하는 원리

배치 메타테이블 알아보기

(schema-{rdbms종류}.sql에 DDL이 작성되어있다.)

JobRepository에는 6개의 테이블이 존재한다.

  • BATCH_JOB_INSTANCE

  • BATCH_JOB_EXECUTION

  • BATCH_JOB_EXECUTION_PARAMS

  • BATCH_JOB_EXECUTION_CONTEXT

  • BATCH_STEP_EXECUTION

  • BATCH_STEP_EXECUTION_CONTEXT

BATCH_JOB_INSTANCE

Job Parameter에 따라 생성되는 테이블이다. Job Parameter는 Spring Batch가 실행될 때 외부에서 받을 수 있는 파라미터로, 같은 Batch Job이더라도 Job Parameter가 다르면, BATCH_JOB_INSTANCE에 기록이되고, Job Parameter가 동일하다면 기록되지 않는다.

필드명
설명

JOB_INSTANCE_ID

BATCH_JOB_INSTANCE 테이블의 PK

VERSION

JOB_NAME

수행한 Batch Job Name

JOB_KEY

잡 이름과 잡 파라미터 해시 값으로, JobInstance를 고유하게 식별하는데 사용하는 값

@Slf4j
@RequiredArgsConstructor
@Configuration
public class SimpleJobConfiguration {
    private final JobBuilderFactory jobBuilderFactory;
    private final StepBuilderFactory stepBuilderFactory;

    @Bean
    public Job simpleJob(){
        return jobBuilderFactory.get("simpleJob")
                .start(simpleStep(null))
                .build();
    }

    @Bean
    @JobScope
    public Step simpleStep(@Value("#{jobParameters[requestDate]}")String requestDate){
        return stepBuilderFactory.get("simpleStep")
                .tasklet((contribution, chunkContext) -> {
                    log.info(">>>>> This is Step1");
                    log.info(">>>>> This is requestDate = {}", requestDate);
                    return RepeatStatus.FINISHED;
                })
                .build();
    }
}

promgram arguements에 새로 추가한 jobParameter를 추가해준 후 실행하면, log도 정상적으로 찍히고, 새로운 BATCH_JOB_INSTANCE가 생긴것을 볼 수 있다.

2021-01-24 23:09:38.687  INFO 35371 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : Job: [SimpleJob: [name=simpleJob]] launched with the following parameters: [{requestDate=20210101}]
2021-01-24 23:09:38.900  INFO 35371 --- [           main] o.s.batch.core.job.SimpleStepHandler     : Executing step: [simpleStep]
2021-01-24 23:09:38.959  INFO 35371 --- [           main] s.b.p.jobs.SimpleJobConfiguration        : >>>>> This is Step1
2021-01-24 23:09:38.959  INFO 35371 --- [           main] s.b.p.jobs.SimpleJobConfiguration        : >>>>> This is requestDate = 20210101
2021-01-24 23:09:38.982  INFO 35371 --- [           main] o.s.batch.core.step.AbstractStep         : Step: [simpleStep] executed in 81ms

만약 동일한 파라미터로 다시 수행을 했을때,

java.lang.IllegalStateException: Failed to execute ApplicationRunner
	at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:798) [spring-boot-2.4.2.jar:2.4.2]
	at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:785) [spring-boot-2.4.2.jar:2.4.2]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:333) [spring-boot-2.4.2.jar:2.4.2]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1311) [spring-boot-2.4.2.jar:2.4.2]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1300) [spring-boot-2.4.2.jar:2.4.2]
	at spring.batch.practice.PracticeApplication.main(PracticeApplication.java:14) [classes/:na]
Caused by: org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException: A job instance already exists and is complete for parameters={requestDate=20210101}.  If you want to run this job again, change the parameters.

같은 파라미터로는 Job을 실행할 수 없다는 오류가 발생하는 것을 볼 수 있다.

즉, 동일한 Job이 Job Parameter가 달라지면 그때마다 BATCH_JOB_INSTANCE에 생성되며, 동일한 Job Parameter는 여러개 존재할 수 없다.

BATCH_JOB_EXECUTION

배치 잡의 실제 실행 기록을 나타낸다. Job이 실행될 떄마다 새 레코드가 해당 테이블에 생성되고, Job이 진행되는 동안 주기적으로 업데이트 된다.

필드
설명

JOB_EXECUTION_ID

PK

VERSION

JOB_INSTANCE_ID

BATCH_JOB_INSTANCE 참조하는 외래키

CREATE_TIME

레코드 생성된 시간

START_TIME

잡 실행이 시작된 시간

END_TIME

잡 실행이 완료된 시간

STATUS

잡 실행의 배치 상태

EXIT_CODE

잡 실행의 종료코드

EXIT_MESSAGE

EXIT_CODE와 관련된 메세지나 스택 트레이스

LAST_UPDATED

레코드가 마지막으로 갱신된 시간

여기서 보면, JOB_INSTANCE_ID는 2개가 있는 것을 볼 수 있다. 이는 각각 파라미터 없이 실행한 simpleJob, requestDate=2021010로 실행한 simpleJob임을 알 수 있따.

JOB_INSTANCE와 JOB_EXECUTION는 부모-자식 관계이며, JOB_EXECUTION는 자신의 부모 JOB_INSTANCE가 성공/실패한 모든 기록을 기록하고 있다.

package spring.batch.practice.jobs;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.core.Job;
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.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Slf4j
@RequiredArgsConstructor
@Configuration
public class SimpleJobConfiguration {
    private final JobBuilderFactory jobBuilderFactory;
    private final StepBuilderFactory stepBuilderFactory;

    @Bean
    public Job simpleJob(){
        return jobBuilderFactory.get("simpleJob")
                .start(simpleStep(null))
                .build();
    }

    @Bean
    @JobScope
    public Step simpleStep(@Value("#{jobParameters[requestDate]}")String requestDate){
        return stepBuilderFactory.get("simpleStep")
                .tasklet((contribution, chunkContext) -> {
                    throw new IllegalArgumentException("step1 실패");
                })
                .build();
    }
    
}

파라미터를 20210102 로 변경한 후에 일부러 실패한 후 다시 똑같은 파라미터로 수행을 하면 다음과 같이 FAILED, COMPLETED 두개의 row가 생긴것을 볼 수 있다. 여기서 알 수 있는점은 수행 결과가 성공한 기록이 있을때만 재수행이 안된다(실패)는 점이다.

BATCH_JOB_EXECUTION_CONTEXT

ExecutionContext 를 저장하는 테이블이다.

필드
설명

JOB_EXECUTION_ID

PK

SHORT_CONTEXT

Trim처리된 SERIALIZED_CONTEXT

SERIALIZED_CONTEXT

직렬화된 ExecutionContext

ExecutionContext를 직렬화하는 방법은 여러가지가 있는데, 스프링 배치 4이전에는 XSteam의 JSON 처리 기능을 기본으로 사용했으나, 4가 출시될 때 Jackson2를 기본적으로 사용하도록 변경됐다.

BATCH_JOB_EXECUTION_PARAMS

Job이 매번 실행될 때 마다 사용된 파라미터를 저장한다. Job 수행시 필요한 모든 파라미터가 저장된다.

필드
설명

JOB_EXECUTION_ID

PK

TYPE_CD

파라미터 값의 타입을 나타내는 문자열

KEY_NAME

파라미터 이름

STRING_VAL

타입이 String인 경우 파라미터의 값

DATE_VAL

타입이 Date인 경우 파라미터의 값

LONG_VAL

타입이 Long인 경우 파라미터의 값

DOUBLE_VAL

타입이 Double인 경우 파라미터의 값

IDENTIFYING

파라미터가 식별되는지 여부를 나타내는 플래그

JOB_EXECUTION으로 그 당시 입력된 Job Parameter값을 담고 있다.

BATCH_STEP_EXECUTION

  • 스텝의 시작, 완료, 상태에 대한 메타데이터를 저장

  • 스텝 분석이 가능하도록 다양한 횟수 값을 추가 저장

  • 읽기 횟수, 처리 횟수, 쓰기 횟수, 건너뛰기 횟수 등 모든 데이터가 저장된다.

필드
설명

STEP_EXECUTION_ID

PK

VERSION

낙관적인 락에 사용되는 레코드의 버전

STEP_NAME

스텝 이름

JOB_EXECUTION_ID

BATCH_JOB_EXECUTION을 참조하는 외래키

START_TIME

스텝 실행 시작 시간

END_TIME

스텝 실행 완료 시간

STATUS

스텝의 배치 상태

COMMIT_COUNT

스텝 실행중 커밋된 트랜잭션 수

READ_COUNT

읽은 아이템 수

FILTER_COUNT

아이템 프로세서가 null을 반환해 필터링된 아이템 수

WRITE_COUNT

기록된 아이템 수

READ_SKIP_COUNT

ItemReader내에서 예외가 발생해 건너뛴 아이템 수

WRITE_SKIP_COUNT

ItemProcessor 내에서 예외가 발생해 건너뛴 아이템 수

PROCESS_SKIP_COUNT

ItemWriter 내에서 예외가 발생해 건너뛴 아이템 수

ROLLBACK_COUNT

스텝 실행에서 롤백된 트랜잭션 수

EXIT_CODE

스텝의 종료코드

EXIT_MESSAGE

스텝 실행에서 반환된 메세지나 스택 트레이스

LAST_UPDATED

레코드가 마지막으로 업데이트 된 시간

BATCH_STEP_EXECUTION_CONTEXT

StepExecution의 ExecutionContext 를 저장하는 테이블로, 스텝 수준에서의 컴포넌트 상태를 저장하는데 사용한다.

필드
설명

STEP_EXECUTION_ID

PK

SHORT_CONTEXT

Trim처리된 SERIALIZED_CONTEXT

SERIALIZED_CONTEXT

직렬화된 ExecutionContext

인메모리 JobRepository

스프링 배치 잡을 개발하거나 단위 테스트를 수행할 때 외부 데이터데이스를 구축하는 작업이 실제로 얻는 이익보다 더 많은 문제를 발생시킬 수 있다.

스프링 배치는 Map 객체를 데이터 저장소로 사용하는 JobRepository 구현체를 제공한다.

Map 객체기반의 JobRepository는 실제 운영 시 사용하지 않으며, 외부 데이터베이스 없이 배치 잡을 실행하려면 멀티 스레딩 및 트랜잭션 기능을 더 잘 지원하는 H2 혹은 HSQLDB와 같은 인메모리 데이터베이스를 사용하는 것을 권장한다.

Batch Infrastructure

@EnableBatchProcessing 어노테이션을 사용하면, 추가적인 구성없이 스프링 배치가 제공하는 JobRepository를 사용할 수 있다.

하지만 JobRepository를 커스터마이징 해야하는 경우도 있으므로, 커스터마이징하는 방법에 대해 추가로 정리할 것이다.

BatchConfigurer

  • org.springframework.batch.core.configuration.annotation.BatchConfigurer

스프링 배치 인프라스트럭처 컴포넌트 구성을 커스터마이징하는데 사용되는 전략 인터페이스이다.

public interface BatchConfigurer {

   JobRepository getJobRepository() throws Exception;

   PlatformTransactionManager getTransactionManager() throws Exception;

   JobLauncher getJobLauncher() throws Exception;

   JobExplorer getJobExplorer() throws Exception;
}

각 메서드는 스프링 배치 인프라스트럭처의 주요 컴포넌트를 제공한다.

  • PlatformTransactionManager는 프레임워크가 제공하는 모든 트랜잭션 관리 시에 스프링 배치가 사용하는 컴포넌트

  • JobExplorer는 JobRepository 데이터를 읽는 용

이 모든 인터페이스를 직접 구현할 필요는 없으며, DefaultBatchConfigurer 를 사용하면 모든 기본 옵션이 제공된다. 일반적인 경우에 DefaultBatchConfigurer 를 상속해 적절한 메서드를 재정의하는 것이 더 쉽다.

JobRepository 커스터마이징

JobRepository는 JobRepositoryFactoryBean 이라는 FactoryBean을 통해 생성된다.

FactoryBean 은 다음 각 애트리뷰트를 커스터마이징 할 수 있는 기능을 제공한다.

접근자 이름
설명

setClobType(int type)

CLOB 컬럼에 사용할 타입을 나타내는 java.sql.Type 값을 받음

setSerializer(ExecutionContextSerializer serializer)

JobExecution, StepExecution의 ExecutionContext를 직렬화/역직렬화 하는데 사용할 ExecutionContextSerializer 구현체 구성에 사용

setLobHandler(LobHandler lobHandler)

실제로 LOB을 취급해야하는 Oracle 예전 버전을 사용할 때 필요한 설정

setMaxVarCharLength(int maxVarCharLength)

짧은 실행 컨텍스트 컬럼, 종료 메세지의 길이를 자르는데 사용한다. 스프링 배치에서 제공하는 스키마를 수정하지 않는 한 변경해서는 안된다.

setDataSource(DataSource dataSource)

JobRepository 와 같이 사용할 DataSource를 설정

setJdbcOperations(JdbcOperations jdbcOperations)

JdbcOperations 인스턴스를 지정하는 setter로, 지정하지 않으면 setDataSource 에 지정한 데이터 소스를 사용해 JdbcOperations를 생성한다.

setDatabaseType(String dbType)

데이터베이스 유형 설정 스프링 배치는 일반적으로 데이터베이스 유형을 자동으로 식별하므로, 특별한 경우 아니면 설정할 필요 없음.

setTablePrefix(String tablePrefix)

모든 테이블 이름에 기본적으로 사용되는 BATCH_ 외의 접두어가 지정될 때 사용

setIncrementerFactory(DataFieldMaxValueIncrementerFactory incrementerFactory)

테이블의 기본키를 증분하는데 사용되는 증분기 팩토리를 지정

setValidateTransactionState(boolean validateTransactionState)

JobExecution 이 생성될 때 기존 트랜잭션이 있는지 여부를 나타내는 플래그 (기본값 : true)

setIsolationLevelForCreate(String isolationLevelForCreate)

setTransactionManager(PlatformTransactionManager transactionManager)

복수 개의 데이터 베이스 사용시, 두 데이터베이스를 동기화할 수 있게 2단계 커밋을 지원하는 TransactionManager를 지정

보통 DefaultBatchConfigurer를 상속해 createJobRepository()를 재정의해야하는 경우는 두개 이상의 데이터 소스가 존재하는 경우이다. 예를 들어 업무 데이터 용도의 데이터 소스와 JobRepository 용도의 데이터 소스가 별도로 각각 존재하면, JobRepository가 사용하는 데이터 소스는 명시적으로 구성해야한다.

public class CustomBatchConfigurer extends DefaultBatchConfigurer {

    @Autowired
    @Qualifier("repositoryDataSource")
    private DataSource dataSource;

    @Override
    protected JobRepository createJobRepository() throws Exception {
        JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
        factory.setDatabaseType(DatabaseType.MYSQL.getProductName());

      	// 테이블명이 BATCH_에서 FOO_로 구성
        factory.setTablePrefix("FOO_");
      
      	// 데이터 생성시 트랜잭션 격리 수준
        factory.setIsolationLevelForCreate("ISOLATION_REPEATABLE_READ"); 
        factory.setDataSource(this.dataSource);
        factory.afterPropertiesSet();
        return factory.getObject();
    }

}
  • InintializingBean.afterPropertiesSet() afterPropertiesSet() 은 InintializingBean 인터페이스 메소드로 BeanFactory에 의해 모든 property 가 설정되고 난 뒤 실행되는 메소드입니다. 주로 실행시점의 custom 초기화 로직이 필요하거나 주입받은 property 를 확인하는 용도로 사용된다.

  • FactoryBean.getObject() : Instance를 생성하거나 획득하여 Spring에서 관리할 객체를 리턴해준다.

BatchConfigurer의 메서드는 스프링 컨테이너에 직접 노출하지 않으므로, 반드시 아래 메서드를 호출해줘야한다.

factory.afterPropertiesSet();
return factory.getObject();

TransactionManager 커스터마이징

public class CustomBatchConfigurer extends DefaultBatchConfigurer {

    @Autowired
    @Qualifier("batchTransactionManager")
    private PlatformTransactionManager transactionManager;

    @Override
    public PlatformTransactionManager getTransactionManager() {
        return this.transactionManager;
    }
}

TransactionManager가 생성되지 않은 경우에 DefaultBatchConfigurer가 기본적으로 setDataSource 수정자 내에서 DataSourceTransactionManager를 자동으로 생성하기 때문에 명시적으로 반환해 구현한 것이다.

JobExplorer 커스터마이징

JobExplorer는 배치 메타데이터를 읽기 전용으로 제공한다.

JobRepository 와 JobExplorer 는 데이터베이스로부터 데이터를 읽어들이는 데 사용되는 모든 애트리뷰트가 동일하다.

JobExplorerFactoryBean 으로 커스터마이징을 할 수 있다.

접근자 이름
설명

setSerializer(ExecutionContextSerializer serializer)

JobExecution, StepExecution의 ExecutionContext를 직렬화/역직렬화 하는데 사용할 ExecutionContextSerializer 구현체 구성에 사용

setLobHandler(LobHandler lobHandler)

실제로 LOB을 취급해야하는 Oracle 예전 버전을 사용할 때 필요한 설정

setDataSource(DataSource dataSource)

JobRepository 와 같이 사용할 DataSource를 설정

setJdbcOperations(JdbcOperations jdbcOperations)

JdbcOperations 인스턴스를 지정하는 setter로, 지정하지 않으면 setDataSource 에 지정한 데이터 소스를 사용해 JdbcOperations를 생성한다.

setTablePrefix(String tablePrefix)

모든 테이블 이름에 기본적으로 사용되는 BATCH_ 외의 접두어가 지정될 때 사용

    @Override
    protected JobExplorer createJobExplorer() throws Exception {
        JobExplorerFactoryBean jobExplorerFactoryBean = new JobExplorerFactoryBean();

        jobExplorerFactoryBean.setDataSource(this.dataSource);
        jobExplorerFactoryBean.setTablePrefix("FOO_");

        jobExplorerFactoryBean.afterPropertiesSet();
        return jobExplorerFactoryBean.getObject();
    }

JobLauncher 커스터마이징

JobLauncher는 스프링 배치 잡을 실행하는 진입점으로, 스프링 부트는 기본적으로 SimpleJobLauncher 를 사용한다. 그러므로, 스프링 부트의 기본 메커니즘으로 Job을 실행할 때는 커스터마이징 할 필요가 없다. 하지만, 별도의 방식으로 Job을 구동하는 방법을 외부에 제공하기 위해 SimpleJobLauncher 동작을 변경할 수 있다.

접근자이름
설명

setJobRepository(JobRepository jobRepository)

사용할 JobRepository 설정

setTaskExecutor(TaskExecutor taskExecutor)

JobLauncher에서 사용할 TaskExecutor 설정 (default : SyncTaskExecutor)

참고

Spring Batch Meta-Data ERD

에 사용되는 레코드 버전

에 사용되는 레코드 버전

JobExecution 엔티티 생성시 사용되는 을 지정 (기본값 : ISOLATION_SERIALIZABLE)

기억보단 기록을 - 3. Spring Batch 가이드 - 메타테이블엿보기
낙관적인 락
낙관적인 락
트랜잭션 직렬화 수준
https://github.com/cheese10yun/TIL/raw/master/assets/batch-obejct-relrationship.png
image-20210124231035080
image-20210124231218392
image-20210124231641820
image-20210124233941054
image-20210124234215270