Compare commits

...

14 Commits

Author SHA1 Message Date
ecbd5aea91 Merge pull request 'dev' (#101) from dev into prd-deploy
Reviewed-on: #101
2025-06-18 14:08:06 +09:00
491f7c7431 Merge pull request '스프링 배치 (운영)6/18_1' (#99) from feature/cha into dev
Reviewed-on: #99
2025-06-18 14:06:48 +09:00
cha
01f9e610f2 스프링 배치 (운영)6/18_1 2025-06-18 14:02:52 +09:00
d5a43e2ae6 Merge pull request '스프링 배치 6/18_1' (#97) from feature/cha into dev
Reviewed-on: #97
2025-06-18 13:41:15 +09:00
cha
7cb8ac8cc5 스프링 배치 6/18_1 2025-06-18 13:40:10 +09:00
59918fe25c Merge pull request '배치 2008 설정 수정(yml, xml. java)' (#95) from feature/cha into dev
Reviewed-on: #95
2025-06-17 16:34:21 +09:00
cha
7d6227b5e5 배치 2008 설정 수정(yml, xml. java) 2025-06-17 16:33:00 +09:00
4e81d7909d Merge pull request '배치 2007 설정 수정' (#93) from feature/cha into dev
Reviewed-on: #93
2025-06-17 15:25:49 +09:00
cha
d2f31f5c34 배치 2007 설정 수정 2025-06-17 15:24:49 +09:00
0c9018e9b0 Merge pull request '배치 2007 설정 수정' (#91) from feature/cha into dev
Reviewed-on: #91
2025-06-17 14:26:41 +09:00
cha
f720e6d19f 배치 2007 설정 수정 2025-06-17 14:25:19 +09:00
d315066402 Merge pull request 'feature/cha' (#89) from feature/cha into dev
Reviewed-on: #89
2025-06-17 13:35:20 +09:00
cha
760b00e8a4 배치 2007 설정 수정 2025-06-17 13:34:27 +09:00
cha
ed7e178ccb 배치 2007 설정 2025-06-17 10:32:32 +09:00
8 changed files with 254 additions and 22 deletions

View File

@ -151,9 +151,9 @@ public class JobLauncherController {
JobParameters jobParameters = JobParameters jobParameters =
new JobParametersBuilder().addDate("time", new Date()).toJobParameters(); new JobParametersBuilder().addDate("time", new Date()).toJobParameters();
if (batchJobEnabled) { //if (batchJobEnabled) {
jobLauncher.run(job, jobParameters); jobLauncher.run(job, jobParameters);
} //}
} }
return "OK"; return "OK";
} }
@ -181,9 +181,9 @@ public class JobLauncherController {
JobParameters jobParameters = JobParameters jobParameters =
new JobParametersBuilder().addDate("time", new Date()).toJobParameters(); new JobParametersBuilder().addDate("time", new Date()).toJobParameters();
if (batchJobEnabled) { //if (batchJobEnabled) {
jobLauncher.run(job, jobParameters); jobLauncher.run(job, jobParameters);
} //}
} }
return "OK"; return "OK";
@ -274,9 +274,9 @@ public class JobLauncherController {
JobParameters jobParameters = JobParameters jobParameters =
new JobParametersBuilder().addDate("time", new Date()).toJobParameters(); new JobParametersBuilder().addDate("time", new Date()).toJobParameters();
if (batchJobEnabled) { // if (batchJobEnabled) {
jobLauncher.run(job, jobParameters); jobLauncher.run(job, jobParameters);
} // }
} }
return "OK"; return "OK";

View File

@ -0,0 +1,72 @@
package com.interplug.qcast.config.batch;
import javax.sql.DataSource;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean;
import org.springframework.batch.item.database.support.DataFieldMaxValueIncrementerFactory;
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.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.transaction.PlatformTransactionManager;
/**
* Spring Batch configuration for SQL Server 2008 without sequence support.
*/
@Configuration
@EnableBatchProcessing
public class BatchConfiguration {
/**
* Configuring JobRepository for SQL Server 2008.
* 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);
factory.setIncrementerFactory(new CustomDefaultDataFieldMaxValueIncrementerFactory(dataSource));
// Use TABLE_PREFIX to map to Spring Batch tables
factory.setTablePrefix("BATCH_");
// Isolation level setting for SQL Server
factory.setIsolationLevelForCreate("ISOLATION_SERIALIZABLE");
// Set to "SQLSERVER" for Spring Batch compatibility
factory.setDatabaseType("SQLSERVER");
// Finalize factory setup
factory.afterPropertiesSet();
return factory.getObject();
}
@Bean
public DataFieldMaxValueIncrementerFactory customIncrementerFactory(DataSource dataSource) {
return new CustomDefaultDataFieldMaxValueIncrementerFactory(dataSource);
}
/**
* TaskExecutor for batch processing (multithreading support).
*/
@Bean
public TaskExecutor batchTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(25);
executor.setThreadNamePrefix("batch-thread-");
executor.initialize();
return executor;
}
}

View File

@ -0,0 +1,22 @@
package com.interplug.qcast.config.batch;
import org.springframework.batch.item.database.support.DefaultDataFieldMaxValueIncrementerFactory;
import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer;
import org.springframework.jdbc.support.incrementer.SqlServerSequenceMaxValueIncrementer;
import javax.sql.DataSource;
public class CustomDefaultDataFieldMaxValueIncrementerFactory extends DefaultDataFieldMaxValueIncrementerFactory {
private final DataSource dataSource;
public CustomDefaultDataFieldMaxValueIncrementerFactory(DataSource dataSource) {
super(dataSource);
this.dataSource = dataSource;
}
@Override
public DataFieldMaxValueIncrementer getIncrementer(String databaseType, String incrementerName) {
CustomIncrementer customIncrementer = new CustomIncrementer(this.dataSource, incrementerName);
return customIncrementer;
}
}

View File

@ -0,0 +1,39 @@
package com.interplug.qcast.config.batch;
import org.springframework.jdbc.support.incrementer.AbstractColumnMaxValueIncrementer;
import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class CustomIncrementer extends AbstractColumnMaxValueIncrementer {
public CustomIncrementer(DataSource dataSource, String incrementerName) {
super(dataSource, incrementerName, "ID");
}
@Override
protected long getNextKey() {
long nextKey = 0;
try (Connection conn = this.getDataSource().getConnection()) {
PreparedStatement psSelect = conn.prepareStatement("SELECT ID FROM " + getIncrementerName() + " WITH (UPDLOCK, HOLDLOCK)");
ResultSet rs = psSelect.executeQuery();
if (rs.next()) {
nextKey = rs.getLong(1);
}
rs.close();
psSelect.close();
PreparedStatement psUpdate = conn.prepareStatement("UPDATE " + getIncrementerName() + " SET ID = ?");
psUpdate.setLong(1, nextKey + 1);
psUpdate.executeUpdate();
psUpdate.close();
} catch (SQLException e) {
throw new RuntimeException("Could not get next key for " + getIncrementerName(), e);
}
return nextKey + 1;
}
}

View File

@ -0,0 +1,94 @@
CREATE TABLE BATCH_JOB_INSTANCE (
JOB_INSTANCE_ID BIGINT NOT NULL PRIMARY KEY ,
VERSION BIGINT NULL,
JOB_NAME VARCHAR(100) NOT NULL,
JOB_KEY VARCHAR(32) NOT NULL,
constraint JOB_INST_UN unique (JOB_NAME, JOB_KEY)
) ;
CREATE TABLE BATCH_JOB_EXECUTION (
JOB_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY ,
VERSION BIGINT NULL,
JOB_INSTANCE_ID BIGINT NOT NULL,
CREATE_TIME DATETIME NOT NULL,
START_TIME DATETIME DEFAULT NULL ,
END_TIME DATETIME DEFAULT NULL ,
STATUS VARCHAR(10) NULL,
EXIT_CODE VARCHAR(2500) NULL,
EXIT_MESSAGE VARCHAR(2500) NULL,
LAST_UPDATED DATETIME NULL,
constraint JOB_INST_EXEC_FK foreign key (JOB_INSTANCE_ID)
references BATCH_JOB_INSTANCE(JOB_INSTANCE_ID)
) ;
CREATE TABLE BATCH_JOB_EXECUTION_PARAMS (
JOB_EXECUTION_ID BIGINT NOT NULL ,
PARAMETER_NAME VARCHAR(100) NOT NULL ,
PARAMETER_TYPE VARCHAR(100) NOT NULL ,
PARAMETER_VALUE VARCHAR(2500) ,
IDENTIFYING CHAR(1) NOT NULL ,
constraint JOB_EXEC_PARAMS_FK foreign key (JOB_EXECUTION_ID)
references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
) ;
CREATE TABLE BATCH_STEP_EXECUTION (
STEP_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY ,
VERSION BIGINT NOT NULL,
STEP_NAME VARCHAR(100) NOT NULL,
JOB_EXECUTION_ID BIGINT NOT NULL,
CREATE_TIME DATETIME NOT NULL,
START_TIME DATETIME DEFAULT NULL ,
END_TIME DATETIME DEFAULT NULL ,
STATUS VARCHAR(10) NULL,
COMMIT_COUNT BIGINT NULL,
READ_COUNT BIGINT NULL,
FILTER_COUNT BIGINT NULL,
WRITE_COUNT BIGINT NULL,
READ_SKIP_COUNT BIGINT NULL,
WRITE_SKIP_COUNT BIGINT NULL,
PROCESS_SKIP_COUNT BIGINT NULL,
ROLLBACK_COUNT BIGINT NULL,
EXIT_CODE VARCHAR(2500) NULL,
EXIT_MESSAGE VARCHAR(2500) NULL,
LAST_UPDATED DATETIME NULL,
constraint JOB_EXEC_STEP_FK foreign key (JOB_EXECUTION_ID)
references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
) ;
CREATE TABLE BATCH_STEP_EXECUTION_CONTEXT (
STEP_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY,
SHORT_CONTEXT VARCHAR(2500) NOT NULL,
SERIALIZED_CONTEXT VARCHAR(MAX) NULL,
constraint STEP_EXEC_CTX_FK foreign key (STEP_EXECUTION_ID)
references BATCH_STEP_EXECUTION(STEP_EXECUTION_ID)
) ;
CREATE TABLE BATCH_JOB_EXECUTION_CONTEXT (
JOB_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY,
SHORT_CONTEXT VARCHAR(2500) NOT NULL,
SERIALIZED_CONTEXT VARCHAR(MAX) NULL,
constraint JOB_EXEC_CTX_FK foreign key (JOB_EXECUTION_ID)
references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
) ;
CREATE TABLE BATCH_JOB_SEQ (
ID BIGINT NOT NULL PRIMARY KEY,
NEXT_VAL BIGINT NOT NULL
);
-- 첫 번째 ID 값 초기화
INSERT INTO BATCH_JOB_SEQ (ID, NEXT_VAL) VALUES (1, 1);
CREATE TABLE BATCH_JOB_EXECUTION_SEQ (
ID BIGINT PRIMARY KEY
);
INSERT INTO BATCH_JOB_EXECUTION_SEQ (ID) VALUES (1);
CREATE TABLE BATCH_STEP_EXECUTION_SEQ (
ID BIGINT NOT NULL PRIMARY KEY
);
-- 초기 키 값을 삽입
INSERT INTO BATCH_STEP_EXECUTION_SEQ (ID) VALUES (0);

View File

@ -15,21 +15,6 @@ spring:
username: pvDBuser username: pvDBuser
maximum-pool-size: 4 maximum-pool-size: 4
pool-name: Master-HikariPool pool-name: Master-HikariPool
# datasource:
# master:
# driver-class-name: net.sf.log4jdbc.sql.jdbcapi.DriverSpy
# jdbc-url: jdbc:log4jdbc:sqlserver://1.248.227.176:1433;databaseName=NEWPVCAD;encrypt=true;trustServerCertificate=true
# username: pvDBuser
# password: ENC(W7owprYnvf7vqwO6Piw4dHfVBCSxE4Ck)
# maximum-pool-size: 4
# pool-name: Master-HikariPool
# read:
# driver-class-name: net.sf.log4jdbc.sql.jdbcapi.DriverSpy
# jdbc-url: jdbc:log4jdbc:sqlserver://1.248.227.176:1433;databaseName=NEWPVCAD;encrypt=true;trustServerCertificate=true
# username: pvDBuser
# password: ENC(W7owprYnvf7vqwO6Piw4dHfVBCSxE4Ck)
# maximum-pool-size: 4
# pool-name: Read-HikariPool
jackson: jackson:
time-zone: Asia/Seoul time-zone: Asia/Seoul
batch: batch:
@ -40,7 +25,6 @@ spring:
enabled: false enabled: false
profiles: profiles:
scheduler: Y scheduler: Y
batch: batch:
job: job:
enabled: true enabled: true

View File

@ -36,4 +36,14 @@
<appender-ref ref="FILE"/> <appender-ref ref="FILE"/>
</root> </root>
<!-- Spring Batch 로깅 레벨 설정 -->
<logger name="org.springframework.batch" level="DEBUG"/>
<!-- JdbcTemplate 로깅 레벨 설정 -->
<logger name="org.springframework.jdbc.core.JdbcTemplate" level="DEBUG"/>
<!-- Hibernate SQL 로깅을 활성화하려면 (선택 사항) -->
<logger name="org.hibernate.SQL" level="DEBUG"/>
<logger name="org.hibernate.type.descriptor.sql.BasicBinder" level="TRACE"/>
</configuration> </configuration>

View File

@ -36,4 +36,15 @@
<!-- <appender-ref ref="FILE" />--> <!-- <appender-ref ref="FILE" />-->
</root> </root>
<!-- Spring Batch 로깅 레벨 설정 -->
<logger name="org.springframework.batch" level="DEBUG"/>
<!-- JdbcTemplate 로깅 레벨 설정 -->
<logger name="org.springframework.jdbc.core.JdbcTemplate" level="DEBUG"/>
<!-- Hibernate SQL 로깅을 활성화하려면 (선택 사항) -->
<logger name="org.hibernate.SQL" level="DEBUG"/>
<logger name="org.hibernate.type.descriptor.sql.BasicBinder" level="TRACE"/>
</configuration> </configuration>