Spring Batch SQL Server 지원을 위한 구성 추가 및 문서화
- BatchConfiguration.java 파일 생성: SQL Server에서 시퀀스 대신 테이블 기반 ID 생성을 위한 JobRepository 커스터마이징. - application-local.yml 수정: SQL Server 예전 버전에서의 배치 설정 추가. - create_batch_id_tables.sql 스크립트 추가: Spring Batch 메타데이터 테이블 및 ID 생성 테이블 생성. - README_BATCH_SEQUENCE_FIX.md 파일 추가: 문제 해결 가이드 및 적용 방법 문서화.
This commit is contained in:
parent
ee37dcdb16
commit
a2c21a2f07
108
README_BATCH_SEQUENCE_FIX.md
Normal file
108
README_BATCH_SEQUENCE_FIX.md
Normal file
@ -0,0 +1,108 @@
|
||||
# Spring Batch Sequence 문제 해결 가이드
|
||||
|
||||
## 문제 상황
|
||||
|
||||
SQL Server의 예전 버전(2012 이전)에서는 sequence를 지원하지 않아 Spring Batch 실행 시 오류가 발생할 수 있습니다.
|
||||
|
||||
## 해결 방법
|
||||
|
||||
### 1. BatchConfiguration 클래스 생성
|
||||
|
||||
`src/main/java/com/interplug/qcast/config/batch/BatchConfiguration.java` 파일이 생성되었습니다.
|
||||
이 클래스는 JobRepository를 커스터마이징하여 SQL Server에 맞는 설정을 적용합니다.
|
||||
|
||||
### 2. application.yml 설정 수정
|
||||
|
||||
`src/main/resources/config/application-local.yml` 파일의 batch 설정이 수정되었습니다:
|
||||
|
||||
```yaml
|
||||
spring:
|
||||
batch:
|
||||
jdbc:
|
||||
initialize-schema: never
|
||||
table-prefix: BATCH_
|
||||
schema: # 스키마가 필요한 경우 설정
|
||||
```
|
||||
|
||||
### 3. 데이터베이스 테이블 생성
|
||||
|
||||
`src/main/resources/db/migration/create_batch_id_tables.sql` 스크립트를 실행하여:
|
||||
|
||||
- Spring Batch 메타데이터 테이블 생성
|
||||
- sequence 대신 사용할 ID 생성 테이블 생성
|
||||
|
||||
## 적용 순서
|
||||
|
||||
1. **데이터베이스 스크립트 실행**
|
||||
|
||||
```sql
|
||||
-- create_batch_id_tables.sql 파일의 내용을 데이터베이스에서 실행
|
||||
```
|
||||
|
||||
2. **애플리케이션 재시작**
|
||||
|
||||
- 새로운 BatchConfiguration이 적용됩니다.
|
||||
|
||||
3. **테스트**
|
||||
- 간단한 배치 작업을 실행하여 정상 동작 확인
|
||||
|
||||
## 주요 변경사항
|
||||
|
||||
### BatchConfiguration.java
|
||||
|
||||
- JobRepository를 커스터마이징
|
||||
- SQL Server 데이터베이스 타입 명시적 설정
|
||||
- 테이블 기반 ID 생성 사용
|
||||
|
||||
### SQL 스크립트
|
||||
|
||||
- `BATCH_JOB_SEQ`, `BATCH_JOB_EXECUTION_SEQ`, `BATCH_STEP_EXECUTION_SEQ` 테이블 생성
|
||||
- Spring Batch 메타데이터 테이블들 생성 (없는 경우)
|
||||
|
||||
## 추가 설정 옵션
|
||||
|
||||
필요에 따라 다음 설정들을 조정할 수 있습니다:
|
||||
|
||||
### application.yml
|
||||
|
||||
```yaml
|
||||
spring:
|
||||
batch:
|
||||
jdbc:
|
||||
initialize-schema: always # 자동으로 테이블 생성 (개발환경)
|
||||
table-prefix: CUSTOM_ # 테이블 prefix 변경
|
||||
schema: dbo # 스키마 명시적 설정
|
||||
```
|
||||
|
||||
### BatchConfiguration.java
|
||||
|
||||
```java
|
||||
// 격리 레벨 변경
|
||||
factory.setIsolationLevelForCreate("ISOLATION_READ_COMMITTED");
|
||||
|
||||
// 커스텀 테이블 prefix
|
||||
factory.setTablePrefix("CUSTOM_BATCH_");
|
||||
```
|
||||
|
||||
## 문제 해결
|
||||
|
||||
### 여전히 sequence 오류가 발생하는 경우:
|
||||
|
||||
1. 데이터베이스에 sequence 관련 객체가 남아있는지 확인
|
||||
2. Spring Batch 메타데이터 테이블을 모두 삭제 후 재생성
|
||||
3. 애플리케이션 캐시 클리어 후 재시작
|
||||
|
||||
### 권한 문제:
|
||||
|
||||
SQL Server에서 테이블 생성 및 ID 생성 테이블 접근 권한이 필요합니다.
|
||||
|
||||
```sql
|
||||
-- 필요한 권한 확인
|
||||
GRANT SELECT, INSERT, UPDATE, DELETE ON BATCH_* TO [username];
|
||||
```
|
||||
|
||||
## 참고사항
|
||||
|
||||
- 이 설정은 SQL Server 2008, 2008 R2, 2012 이전 버전에서 사용
|
||||
- SQL Server 2012 이후 버전에서도 호환성을 위해 사용 가능
|
||||
- 운영환경에서는 `initialize-schema: never`로 설정 권장
|
||||
@ -0,0 +1,57 @@
|
||||
package com.interplug.qcast.config.batch;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import org.springframework.batch.core.repository.JobRepository;
|
||||
import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean;
|
||||
import org.springframework.batch.support.DatabaseType;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
import org.springframework.jdbc.support.incrementer.SqlServerMaxValueIncrementer;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
|
||||
/**
|
||||
* Spring Batch Configuration for SQL Server without sequence support
|
||||
*/
|
||||
@Configuration
|
||||
public class BatchConfiguration {
|
||||
|
||||
/**
|
||||
* Custom JobRepository that uses table-based ID generation instead of sequences
|
||||
*/
|
||||
@Bean
|
||||
@Primary
|
||||
public JobRepository jobRepository(DataSource dataSource, PlatformTransactionManager transactionManager) throws Exception {
|
||||
JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
|
||||
factory.setDataSource(dataSource);
|
||||
factory.setTransactionManager(transactionManager);
|
||||
|
||||
// 테이블 prefix 설정
|
||||
factory.setTablePrefix("BATCH_");
|
||||
|
||||
// 격리 레벨 설정
|
||||
factory.setIsolationLevelForCreate("ISOLATION_SERIALIZABLE");
|
||||
|
||||
// SQL Server 데이터베이스 타입 설정
|
||||
factory.setDatabaseType(DatabaseType.SQLSERVER.getProductName());
|
||||
|
||||
factory.afterPropertiesSet();
|
||||
return factory.getObject();
|
||||
}
|
||||
|
||||
/**
|
||||
* TaskExecutor for async batch processing
|
||||
*/
|
||||
@Bean
|
||||
public TaskExecutor batchTaskExecutor() {
|
||||
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||
executor.setCorePoolSize(5);
|
||||
executor.setMaxPoolSize(10);
|
||||
executor.setQueueCapacity(25);
|
||||
executor.setThreadNamePrefix("batch-");
|
||||
executor.initialize();
|
||||
return executor;
|
||||
}
|
||||
}
|
||||
@ -35,6 +35,9 @@ spring:
|
||||
batch:
|
||||
jdbc:
|
||||
initialize-schema: never
|
||||
# SQL Server 예전 버전에서 sequence 대신 table 기반 ID 생성 사용
|
||||
table-prefix: BATCH_
|
||||
schema: # 스키마가 필요한 경우 설정
|
||||
job:
|
||||
names: ${job.name:NONE}
|
||||
enabled: false
|
||||
@ -68,4 +71,4 @@ file:
|
||||
ini.drawing.img.path: https://files.hanasys.jp/Drawing
|
||||
|
||||
front:
|
||||
url: http://localhost:8080
|
||||
url: http://localhost:8080
|
||||
|
||||
125
src/main/resources/db/migration/create_batch_id_tables.sql
Normal file
125
src/main/resources/db/migration/create_batch_id_tables.sql
Normal file
@ -0,0 +1,125 @@
|
||||
-- Spring Batch용 ID 생성 테이블 생성 (SQL Server 예전 버전용)
|
||||
-- sequence 대신 테이블 기반 ID 생성을 사용
|
||||
|
||||
-- Job Instance ID 생성 테이블
|
||||
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[BATCH_JOB_SEQ]') AND type in (N'U'))
|
||||
BEGIN
|
||||
CREATE TABLE BATCH_JOB_SEQ (
|
||||
ID BIGINT NOT NULL
|
||||
);
|
||||
INSERT INTO BATCH_JOB_SEQ VALUES (0);
|
||||
END
|
||||
|
||||
-- Job Execution ID 생성 테이블
|
||||
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[BATCH_JOB_EXECUTION_SEQ]') AND type in (N'U'))
|
||||
BEGIN
|
||||
CREATE TABLE BATCH_JOB_EXECUTION_SEQ (
|
||||
ID BIGINT NOT NULL
|
||||
);
|
||||
INSERT INTO BATCH_JOB_EXECUTION_SEQ VALUES (0);
|
||||
END
|
||||
|
||||
-- Step Execution ID 생성 테이블
|
||||
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[BATCH_STEP_EXECUTION_SEQ]') AND type in (N'U'))
|
||||
BEGIN
|
||||
CREATE TABLE BATCH_STEP_EXECUTION_SEQ (
|
||||
ID BIGINT NOT NULL
|
||||
);
|
||||
INSERT INTO BATCH_STEP_EXECUTION_SEQ VALUES (0);
|
||||
END
|
||||
|
||||
-- 기존 Spring Batch 메타데이터 테이블들이 없는 경우 생성
|
||||
-- Job Instance 테이블
|
||||
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[BATCH_JOB_INSTANCE]') AND type in (N'U'))
|
||||
BEGIN
|
||||
CREATE TABLE BATCH_JOB_INSTANCE (
|
||||
JOB_INSTANCE_ID BIGINT IDENTITY PRIMARY KEY,
|
||||
VERSION BIGINT,
|
||||
JOB_NAME VARCHAR(100) NOT NULL,
|
||||
JOB_KEY VARCHAR(32) NOT NULL,
|
||||
constraint JOB_INST_UN unique (JOB_NAME, JOB_KEY)
|
||||
);
|
||||
END
|
||||
|
||||
-- Job Execution 테이블
|
||||
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[BATCH_JOB_EXECUTION]') AND type in (N'U'))
|
||||
BEGIN
|
||||
CREATE TABLE BATCH_JOB_EXECUTION (
|
||||
JOB_EXECUTION_ID BIGINT IDENTITY PRIMARY KEY,
|
||||
VERSION BIGINT,
|
||||
JOB_INSTANCE_ID BIGINT NOT NULL,
|
||||
CREATE_TIME DATETIME2 NOT NULL,
|
||||
START_TIME DATETIME2 DEFAULT NULL,
|
||||
END_TIME DATETIME2 DEFAULT NULL,
|
||||
STATUS VARCHAR(10),
|
||||
EXIT_CODE VARCHAR(2500),
|
||||
EXIT_MESSAGE VARCHAR(2500),
|
||||
LAST_UPDATED DATETIME2,
|
||||
JOB_CONFIGURATION_LOCATION VARCHAR(2500) NULL,
|
||||
constraint JOB_INST_EXEC_FK foreign key (JOB_INSTANCE_ID) references BATCH_JOB_INSTANCE(JOB_INSTANCE_ID)
|
||||
);
|
||||
END
|
||||
|
||||
-- Job Execution Parameters 테이블
|
||||
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[BATCH_JOB_EXECUTION_PARAMS]') AND type in (N'U'))
|
||||
BEGIN
|
||||
CREATE TABLE BATCH_JOB_EXECUTION_PARAMS (
|
||||
JOB_EXECUTION_ID BIGINT NOT NULL,
|
||||
TYPE_CD VARCHAR(6) NOT NULL,
|
||||
KEY_NAME VARCHAR(100) NOT NULL,
|
||||
STRING_VAL VARCHAR(250),
|
||||
DATE_VAL DATETIME2 DEFAULT NULL,
|
||||
LONG_VAL BIGINT,
|
||||
DOUBLE_VAL DOUBLE PRECISION,
|
||||
IDENTIFYING CHAR(1) NOT NULL,
|
||||
constraint JOB_EXEC_PARAMS_FK foreign key (JOB_EXECUTION_ID) references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
|
||||
);
|
||||
END
|
||||
|
||||
-- Step Execution 테이블
|
||||
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[BATCH_STEP_EXECUTION]') AND type in (N'U'))
|
||||
BEGIN
|
||||
CREATE TABLE BATCH_STEP_EXECUTION (
|
||||
STEP_EXECUTION_ID BIGINT IDENTITY PRIMARY KEY,
|
||||
VERSION BIGINT NOT NULL,
|
||||
STEP_NAME VARCHAR(100) NOT NULL,
|
||||
JOB_EXECUTION_ID BIGINT NOT NULL,
|
||||
START_TIME DATETIME2 NOT NULL,
|
||||
END_TIME DATETIME2 DEFAULT NULL,
|
||||
STATUS VARCHAR(10),
|
||||
COMMIT_COUNT BIGINT,
|
||||
READ_COUNT BIGINT,
|
||||
FILTER_COUNT BIGINT,
|
||||
WRITE_COUNT BIGINT,
|
||||
READ_SKIP_COUNT BIGINT,
|
||||
WRITE_SKIP_COUNT BIGINT,
|
||||
PROCESS_SKIP_COUNT BIGINT,
|
||||
ROLLBACK_COUNT BIGINT,
|
||||
EXIT_CODE VARCHAR(2500),
|
||||
EXIT_MESSAGE VARCHAR(2500),
|
||||
LAST_UPDATED DATETIME2,
|
||||
constraint JOB_EXEC_STEP_FK foreign key (JOB_EXECUTION_ID) references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
|
||||
);
|
||||
END
|
||||
|
||||
-- Step Execution Context 테이블
|
||||
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[BATCH_STEP_EXECUTION_CONTEXT]') AND type in (N'U'))
|
||||
BEGIN
|
||||
CREATE TABLE BATCH_STEP_EXECUTION_CONTEXT (
|
||||
STEP_EXECUTION_ID BIGINT PRIMARY KEY,
|
||||
SHORT_CONTEXT VARCHAR(2500) NOT NULL,
|
||||
SERIALIZED_CONTEXT TEXT,
|
||||
constraint STEP_EXEC_CTX_FK foreign key (STEP_EXECUTION_ID) references BATCH_STEP_EXECUTION(STEP_EXECUTION_ID)
|
||||
);
|
||||
END
|
||||
|
||||
-- Job Execution Context 테이블
|
||||
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[BATCH_JOB_EXECUTION_CONTEXT]') AND type in (N'U'))
|
||||
BEGIN
|
||||
CREATE TABLE BATCH_JOB_EXECUTION_CONTEXT (
|
||||
JOB_EXECUTION_ID BIGINT PRIMARY KEY,
|
||||
SHORT_CONTEXT VARCHAR(2500) NOT NULL,
|
||||
SERIALIZED_CONTEXT TEXT,
|
||||
constraint JOB_EXEC_CTX_FK foreign key (JOB_EXECUTION_ID) references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
|
||||
);
|
||||
END
|
||||
Loading…
x
Reference in New Issue
Block a user