//Google AdSense
Batch ?
  • 일괄처리를 의미합니다.
  • 대용량 데이터를 고성능으로 처리합니다.
  • 자동화로 사용자의 개입 없이 처리할 수 있습니다.
  • 잘못된 데이터를 충돌, 중단 없이 처리합니다.
  • 추적 가능한 logging과 알림으로 신뢰성이 높습니다.

주의사항
  • 복잡한 로직을 피해야합니다.
  • 처리 데이터에 대한 예외 상황이 발생하지 않도록 무결성을 보장해야 합니다.
  • 네트워크 비용을 절감해야합니다.
💥Spring Boot Batch는 Scheduler를 제공하지 않습니다!
  • 구현된 Spring Boot Batch를 별도의 Scheduling Framework에 적용하여 원하는 시간 혹은 이벤트 상황에서 실행하고 이력을 관리해야 합니다.

 

batch의 job과 step의 관계는 이해했다.

job안에 steps가 포함되어있고 step은 tasklet이나 [reader|prossecor|writer] 를 통해 작업을 수행한다.

package batch.practice;

import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;

@EnableBatchProcessing
@SpringBootApplication
//@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
public class SpringBatchExample210428001Application {

	public static void main(String[] args) {
		SpringApplication.run(SpringBatchExample210428001Application.class, args);
	}

}
package batch.practice.job;

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.StepBuilderFactory;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@RequiredArgsConstructor
@Configuration
public class SimpleJobConfiguration {
	private final JobBuilderFactory jobBuilderFactory;
	private final StepBuilderFactory stepBuilderFactory;
	
	@Bean
	public Job simpleJob () {
		return jobBuilderFactory.get("job001")
				.start(simpleStep01())
				.build();
	}
	
	@Bean
	public Step simpleStep01 () {
		return stepBuilderFactory.get("step001")
				.tasklet((contribution, chunkContext) -> {
					log.info("++++++++++ step001 excute ++++++++++");
					return RepeatStatus.FINISHED;
				})
				.build();
	}
	
}

MySQL DB와 연동하기 위해서 dependencies 추가 설정

build.gradle
plugins {
	id 'org.springframework.boot' version '2.3.10.RELEASE'
	id 'io.spring.dependency-management' version '1.0.11.RELEASE'
	id 'java'
}

group = 'batch'
version = '21.04.30.001 batch practice'
sourceCompatibility = '1.8'

configurations {
	compileOnly {
		extendsFrom annotationProcessor
	}
}

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-batch'
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    compileOnly 'org.projectlombok:lombok'
    runtimeOnly 'com.h2database:h2'
    runtimeOnly 'mysql:mysql-connector-java'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testImplementation 'org.springframework.batch:spring-batch-test'
}

test {
	useJUnitPlatform()
}

MySQL DB에 Spring Batch Metadata Table들을 생성했다.

  • batch가 동작하는데에 꼭 필요함!
  • H2DB의 경우 boot시 자동으로 생성해주지만 Oracle, MySQL DB는 schema를 찾아 수동으로 생성해야한다.
schema-mysql.sql
-- Autogenerated: do not edit this file

CREATE TABLE BATCH_JOB_INSTANCE  (
	JOB_INSTANCE_ID BIGINT  NOT NULL 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)
) ENGINE=InnoDB;

CREATE TABLE BATCH_JOB_EXECUTION  (
	JOB_EXECUTION_ID BIGINT  NOT NULL PRIMARY KEY ,
	VERSION BIGINT  ,
	JOB_INSTANCE_ID BIGINT NOT NULL,
	CREATE_TIME DATETIME(6) NOT NULL,
	START_TIME DATETIME(6) DEFAULT NULL ,
	END_TIME DATETIME(6) DEFAULT NULL ,
	STATUS VARCHAR(10) ,
	EXIT_CODE VARCHAR(2500) ,
	EXIT_MESSAGE VARCHAR(2500) ,
	LAST_UPDATED DATETIME(6),
	JOB_CONFIGURATION_LOCATION VARCHAR(2500) NULL,
	constraint JOB_INST_EXEC_FK foreign key (JOB_INSTANCE_ID)
	references BATCH_JOB_INSTANCE(JOB_INSTANCE_ID)
) ENGINE=InnoDB;

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 DATETIME(6) 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)
) ENGINE=InnoDB;

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,
	START_TIME DATETIME(6) NOT NULL ,
	END_TIME DATETIME(6) 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 DATETIME(6),
	constraint JOB_EXEC_STEP_FK foreign key (JOB_EXECUTION_ID)
	references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID)
) ENGINE=InnoDB;

CREATE TABLE BATCH_STEP_EXECUTION_CONTEXT  (
	STEP_EXECUTION_ID BIGINT NOT NULL 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)
) ENGINE=InnoDB;

CREATE TABLE BATCH_JOB_EXECUTION_CONTEXT  (
	JOB_EXECUTION_ID BIGINT NOT NULL 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)
) ENGINE=InnoDB;

CREATE TABLE BATCH_STEP_EXECUTION_SEQ (
	ID BIGINT NOT NULL,
	UNIQUE_KEY CHAR(1) NOT NULL,
	constraint UNIQUE_KEY_UN unique (UNIQUE_KEY)
) ENGINE=InnoDB;

INSERT INTO BATCH_STEP_EXECUTION_SEQ (ID, UNIQUE_KEY) select * from (select 0 as ID, '0' as UNIQUE_KEY) as tmp where not exists(select * from BATCH_STEP_EXECUTION_SEQ);

CREATE TABLE BATCH_JOB_EXECUTION_SEQ (
	ID BIGINT NOT NULL,
	UNIQUE_KEY CHAR(1) NOT NULL,
	constraint UNIQUE_KEY_UN unique (UNIQUE_KEY)
) ENGINE=InnoDB;

INSERT INTO BATCH_JOB_EXECUTION_SEQ (ID, UNIQUE_KEY) select * from (select 0 as ID, '0' as UNIQUE_KEY) as tmp where not exists(select * from BATCH_JOB_EXECUTION_SEQ);

CREATE TABLE BATCH_JOB_SEQ (
	ID BIGINT NOT NULL,
	UNIQUE_KEY CHAR(1) NOT NULL,
	constraint UNIQUE_KEY_UN unique (UNIQUE_KEY)
) ENGINE=InnoDB;

INSERT INTO BATCH_JOB_SEQ (ID, UNIQUE_KEY) select * from (select 0 as ID, '0' as UNIQUE_KEY) as tmp where not exists(select * from BATCH_JOB_SEQ);

Run 했을 경우의 error log
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.4.5)

2021-04-28 16:55:19.464  INFO 19748 --- [  restartedMain] p.SpringBatchExample210428001Application : Starting SpringBatchExample210428001Application using Java 15.0.2 on DESKTOP-C7P9M2O with PID 19748 (--- \springBatchExample210428001\bin\main started by *** in --- \springBatchExample210428001)
2021-04-28 16:55:19.469  INFO 19748 --- [  restartedMain] p.SpringBatchExample210428001Application : No active profile set, falling back to default profiles: default
2021-04-28 16:55:19.550  INFO 19748 --- [  restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable
2021-04-28 16:55:19.550  INFO 19748 --- [  restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG'
2021-04-28 16:55:20.736  INFO 19748 --- [  restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Multiple Spring Data modules found, entering strict repository configuration mode!
2021-04-28 16:55:20.739  INFO 19748 --- [  restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JDBC repositories in DEFAULT mode.
2021-04-28 16:55:20.752  INFO 19748 --- [  restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 8 ms. Found 0 JDBC repository interfaces.
2021-04-28 16:55:20.769  INFO 19748 --- [  restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Multiple Spring Data modules found, entering strict repository configuration mode!
2021-04-28 16:55:20.771  INFO 19748 --- [  restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2021-04-28 16:55:20.782  INFO 19748 --- [  restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 3 ms. Found 0 JPA repository interfaces.
2021-04-28 16:55:21.584  INFO 19748 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2021-04-28 16:55:21.600  INFO 19748 --- [  restartedMain] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2021-04-28 16:55:21.601  INFO 19748 --- [  restartedMain] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.45]
2021-04-28 16:55:21.810  INFO 19748 --- [  restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2021-04-28 16:55:21.811  INFO 19748 --- [  restartedMain] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 2259 ms
2021-04-28 16:55:21.918  WARN 19748 --- [  restartedMain] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'inMemoryDatabaseShutdownExecutor' defined in class path resource [org/springframework/boot/devtools/autoconfigure/DevToolsDataSourceAutoConfiguration.class]: Unsatisfied dependency expressed through method 'inMemoryDatabaseShutdownExecutor' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.zaxxer.hikari.HikariDataSource]: Factory method 'dataSource' threw exception; nested exception is java.lang.IllegalStateException: Cannot load driver class: com.mysql.cj.jdbc.Driver
2021-04-28 16:55:21.922  INFO 19748 --- [  restartedMain] o.apache.catalina.core.StandardService   : Stopping service [Tomcat]
2021-04-28 16:55:21.942  INFO 19748 --- [  restartedMain] ConditionEvaluationReportLoggingListener : 

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2021-04-28 16:55:21.978 ERROR 19748 --- [  restartedMain] o.s.boot.SpringApplication               : Application run failed

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'inMemoryDatabaseShutdownExecutor' defined in class path resource [org/springframework/boot/devtools/autoconfigure/DevToolsDataSourceAutoConfiguration.class]: Unsatisfied dependency expressed through method 'inMemoryDatabaseShutdownExecutor' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.zaxxer.hikari.HikariDataSource]: Factory method 'dataSource' threw exception; nested exception is java.lang.IllegalStateException: Cannot load driver class: com.mysql.cj.jdbc.Driver
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:800) ~[spring-beans-5.3.6.jar:5.3.6]
	at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:541) ~[spring-beans-5.3.6.jar:5.3.6]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1334) ~[spring-beans-5.3.6.jar:5.3.6]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1177) ~[spring-beans-5.3.6.jar:5.3.6]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:564) ~[spring-beans-5.3.6.jar:5.3.6]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524) ~[spring-beans-5.3.6.jar:5.3.6]
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.6.jar:5.3.6]
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.6.jar:5.3.6]
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.6.jar:5.3.6]
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.6.jar:5.3.6]
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322) ~[spring-beans-5.3.6.jar:5.3.6]
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.6.jar:5.3.6]
	at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1154) ~[spring-context-5.3.6.jar:5.3.6]
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:908) ~[spring-context-5.3.6.jar:5.3.6]
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.6.jar:5.3.6]
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:144) ~[spring-boot-2.4.5.jar:2.4.5]
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:782) ~[spring-boot-2.4.5.jar:2.4.5]
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:774) ~[spring-boot-2.4.5.jar:2.4.5]
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:439) ~[spring-boot-2.4.5.jar:2.4.5]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:339) ~[spring-boot-2.4.5.jar:2.4.5]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1340) ~[spring-boot-2.4.5.jar:2.4.5]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1329) ~[spring-boot-2.4.5.jar:2.4.5]
	at batch.practice.SpringBatchExample210428001Application.main(SpringBatchExample210428001Application.java:15) ~[main/:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:564) ~[na:na]
	at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) ~[spring-boot-devtools-2.4.5.jar:2.4.5]
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.zaxxer.hikari.HikariDataSource]: Factory method 'dataSource' threw exception; nested exception is java.lang.IllegalStateException: Cannot load driver class: com.mysql.cj.jdbc.Driver
	at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:658) ~[spring-beans-5.3.6.jar:5.3.6]
	at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:638) ~[spring-beans-5.3.6.jar:5.3.6]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1334) ~[spring-beans-5.3.6.jar:5.3.6]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1177) ~[spring-beans-5.3.6.jar:5.3.6]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:564) ~[spring-beans-5.3.6.jar:5.3.6]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524) ~[spring-beans-5.3.6.jar:5.3.6]
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.6.jar:5.3.6]
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.6.jar:5.3.6]
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.6.jar:5.3.6]
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.6.jar:5.3.6]
	at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) ~[spring-beans-5.3.6.jar:5.3.6]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1380) ~[spring-beans-5.3.6.jar:5.3.6]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1300) ~[spring-beans-5.3.6.jar:5.3.6]
	at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:887) ~[spring-beans-5.3.6.jar:5.3.6]
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791) ~[spring-beans-5.3.6.jar:5.3.6]
	... 27 common frames omitted
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.zaxxer.hikari.HikariDataSource]: Factory method 'dataSource' threw exception; nested exception is java.lang.IllegalStateException: Cannot load driver class: com.mysql.cj.jdbc.Driver
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185) ~[spring-beans-5.3.6.jar:5.3.6]
	at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653) ~[spring-beans-5.3.6.jar:5.3.6]
	... 41 common frames omitted
Caused by: java.lang.IllegalStateException: Cannot load driver class: com.mysql.cj.jdbc.Driver
	at org.springframework.util.Assert.state(Assert.java:97) ~[spring-core-5.3.6.jar:5.3.6]
	at org.springframework.boot.autoconfigure.jdbc.DataSourceProperties.determineDriverClassName(DataSourceProperties.java:224) ~[spring-boot-autoconfigure-2.4.5.jar:2.4.5]
	at org.springframework.boot.autoconfigure.jdbc.DataSourceProperties.initializeDataSourceBuilder(DataSourceProperties.java:176) ~[spring-boot-autoconfigure-2.4.5.jar:2.4.5]
	at org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration.createDataSource(DataSourceConfiguration.java:48) ~[spring-boot-autoconfigure-2.4.5.jar:2.4.5]
	at org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$Hikari.dataSource(DataSourceConfiguration.java:90) ~[spring-boot-autoconfigure-2.4.5.jar:2.4.5]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:564) ~[na:na]
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ~[spring-beans-5.3.6.jar:5.3.6]
	... 42 common frames omitted

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'inMemoryDatabaseShutdownExecutor' defined in class path resource [org/springframework/boot/devtools/autoconfigure/DevToolsDataSourceAutoConfiguration.class]: Unsatisfied dependency expressed through method 'inMemoryDatabaseShutdownExecutor' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.zaxxer.hikari.HikariDataSource]: Factory method 'dataSource' threw exception; nested exception is java.lang.IllegalStateException: Cannot load driver class: com.mysql.cj.jdbc.Driver
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.zaxxer.hikari.HikariDataSource]: Factory method 'dataSource' threw exception; nested exception is java.lang.IllegalStateException: Cannot load driver class: com.mysql.cj.jdbc.Driver
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.zaxxer.hikari.HikariDataSource]: Factory method 'dataSource' threw exception; nested exception is java.lang.IllegalStateException: Cannot load driver class: com.mysql.cj.jdbc.Driver
Caused by: java.lang.IllegalStateException: Cannot load driver class: com.mysql.cj.jdbc.Driver

properties나 java codes를 변경해도 error에 변화가 없다...

뭐가 잘못됐을까!?

spring batch 공부도 할 겸 batch job, step 작성부터 다시 시작해봐야겠다! 😫


210430

external Dependencies를 확인해보니 mysql connector가 없어서

gradle>refresh gradle project 해주니 의존성 추가가 되었다!

잘 연결됩니당 ☺👍👍👍!!

 

Spring Batch를 통해 1~100까지 로그로 출력하기

package batch.practice.job;

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.StepBuilderFactory;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Slf4j						//log 사용을 위한 lombok annotation
@RequiredArgsConstructor	//생성자 DI를 위한 lombok annotation
@Configuration				//Spring batch의 Job은 @Configuration annotation으로 등록 후 사용
public class SimpleJobConfiguration002 {
	private final JobBuilderFactory jobBuilderFactory;
	private final StepBuilderFactory stepBuilderFactory;
			
	@Bean
	public Job simpleJob1() {
		log.info("========== START simpleJob");

		return jobBuilderFactory.get("simpleJob1")	//Batch Job을 생성하고 builder를 통해 이름 지정
				.start(simpleStep1())				//execute 할 step or sequence of steps
				.build();
	};
	
	
			
	@Bean
	public Step simpleStep1() {
		return stepBuilderFactory.get("simpleStep1")			//Batch Step을 생성하고 builder를 통해 이름 지정
				.tasklet((contribution, chunkContext) -> {		//Step 안에서 수행될 기능을 명시
					for(int i = 0; i < 100 ; i ++) {			//	- Tasklet은 Step 안에서 단일로 수행될 커스텀 기능 선언
					log.info(">>>>>  "+(i+1)+"  <<<<<");
					}					
					return RepeatStatus.FINISHED;
				})
				.build();				
	};
					
};
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.4.5)

2021-04-27 13:42:11.560  INFO 27484 --- [  restartedMain] b.p.BatchExample210427001Application     : Starting BatchExample210427001Application using Java 15.0.2 on DESKTOP-C7P9M2O with PID 27484 (-)
2021-04-27 13:42:11.564  INFO 27484 --- [  restartedMain] b.p.BatchExample210427001Application     : No active profile set, falling back to default profiles: default
2021-04-27 13:42:11.642  INFO 27484 --- [  restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable
2021-04-27 13:42:12.367  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : ========== START simpleJob
2021-04-27 13:42:12.583  INFO 27484 --- [  restartedMain] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729
2021-04-27 13:42:12.605  INFO 27484 --- [  restartedMain] b.p.BatchExample210427001Application     : Started BatchExample210427001Application in 1.483 seconds (JVM running for 3.024)
2021-04-27 13:42:12.607  INFO 27484 --- [  restartedMain] o.s.b.a.b.JobLauncherApplicationRunner   : Running default command line with: []
2021-04-27 13:42:12.608  WARN 27484 --- [  restartedMain] o.s.b.c.c.a.DefaultBatchConfigurer       : No datasource was provided...using a Map based JobRepository
2021-04-27 13:42:12.608  WARN 27484 --- [  restartedMain] o.s.b.c.c.a.DefaultBatchConfigurer       : No transaction manager was provided, using a ResourcelessTransactionManager
2021-04-27 13:42:12.628  INFO 27484 --- [  restartedMain] o.s.b.c.l.support.SimpleJobLauncher      : No TaskExecutor has been set, defaulting to synchronous executor.
2021-04-27 13:42:12.662  INFO 27484 --- [  restartedMain] o.s.b.c.l.support.SimpleJobLauncher      : Job: [SimpleJob: [name=simpleJob1]] launched with the following parameters: [{}]
2021-04-27 13:42:12.700  INFO 27484 --- [  restartedMain] o.s.batch.core.job.SimpleStepHandler     : Executing step: [simpleStep1]
2021-04-27 13:42:12.711  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  1  <<<<<
2021-04-27 13:42:12.712  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  2  <<<<<
2021-04-27 13:42:12.712  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  3  <<<<<
2021-04-27 13:42:12.712  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  4  <<<<<
2021-04-27 13:42:12.712  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  5  <<<<<
2021-04-27 13:42:12.712  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  6  <<<<<
2021-04-27 13:42:12.712  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  7  <<<<<
2021-04-27 13:42:12.712  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  8  <<<<<
2021-04-27 13:42:12.712  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  9  <<<<<
2021-04-27 13:42:12.712  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  10  <<<<<
2021-04-27 13:42:12.712  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  11  <<<<<
2021-04-27 13:42:12.712  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  12  <<<<<
2021-04-27 13:42:12.712  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  13  <<<<<
2021-04-27 13:42:12.713  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  14  <<<<<
2021-04-27 13:42:12.713  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  15  <<<<<
2021-04-27 13:42:12.713  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  16  <<<<<
2021-04-27 13:42:12.713  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  17  <<<<<
2021-04-27 13:42:12.713  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  18  <<<<<
2021-04-27 13:42:12.713  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  19  <<<<<
2021-04-27 13:42:12.713  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  20  <<<<<
2021-04-27 13:42:12.713  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  21  <<<<<
2021-04-27 13:42:12.713  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  22  <<<<<
2021-04-27 13:42:12.713  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  23  <<<<<
2021-04-27 13:42:12.713  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  24  <<<<<
2021-04-27 13:42:12.713  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  25  <<<<<
2021-04-27 13:42:12.713  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  26  <<<<<
2021-04-27 13:42:12.713  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  27  <<<<<
2021-04-27 13:42:12.713  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  28  <<<<<
2021-04-27 13:42:12.714  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  29  <<<<<
2021-04-27 13:42:12.714  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  30  <<<<<
2021-04-27 13:42:12.714  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  31  <<<<<
2021-04-27 13:42:12.714  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  32  <<<<<
2021-04-27 13:42:12.714  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  33  <<<<<
2021-04-27 13:42:12.714  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  34  <<<<<
2021-04-27 13:42:12.714  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  35  <<<<<
2021-04-27 13:42:12.714  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  36  <<<<<
2021-04-27 13:42:12.714  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  37  <<<<<
2021-04-27 13:42:12.714  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  38  <<<<<
2021-04-27 13:42:12.715  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  39  <<<<<
2021-04-27 13:42:12.715  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  40  <<<<<
2021-04-27 13:42:12.715  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  41  <<<<<
2021-04-27 13:42:12.715  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  42  <<<<<
2021-04-27 13:42:12.715  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  43  <<<<<
2021-04-27 13:42:12.715  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  44  <<<<<
2021-04-27 13:42:12.715  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  45  <<<<<
2021-04-27 13:42:12.715  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  46  <<<<<
2021-04-27 13:42:12.715  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  47  <<<<<
2021-04-27 13:42:12.715  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  48  <<<<<
2021-04-27 13:42:12.715  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  49  <<<<<
2021-04-27 13:42:12.715  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  50  <<<<<
2021-04-27 13:42:12.715  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  51  <<<<<
2021-04-27 13:42:12.715  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  52  <<<<<
2021-04-27 13:42:12.715  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  53  <<<<<
2021-04-27 13:42:12.715  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  54  <<<<<
2021-04-27 13:42:12.716  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  55  <<<<<
2021-04-27 13:42:12.716  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  56  <<<<<
2021-04-27 13:42:12.716  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  57  <<<<<
2021-04-27 13:42:12.716  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  58  <<<<<
2021-04-27 13:42:12.716  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  59  <<<<<
2021-04-27 13:42:12.716  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  60  <<<<<
2021-04-27 13:42:12.716  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  61  <<<<<
2021-04-27 13:42:12.716  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  62  <<<<<
2021-04-27 13:42:12.716  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  63  <<<<<
2021-04-27 13:42:12.716  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  64  <<<<<
2021-04-27 13:42:12.716  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  65  <<<<<
2021-04-27 13:42:12.716  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  66  <<<<<
2021-04-27 13:42:12.716  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  67  <<<<<
2021-04-27 13:42:12.716  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  68  <<<<<
2021-04-27 13:42:12.716  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  69  <<<<<
2021-04-27 13:42:12.716  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  70  <<<<<
2021-04-27 13:42:12.716  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  71  <<<<<
2021-04-27 13:42:12.716  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  72  <<<<<
2021-04-27 13:42:12.716  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  73  <<<<<
2021-04-27 13:42:12.716  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  74  <<<<<
2021-04-27 13:42:12.716  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  75  <<<<<
2021-04-27 13:42:12.716  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  76  <<<<<
2021-04-27 13:42:12.717  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  77  <<<<<
2021-04-27 13:42:12.717  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  78  <<<<<
2021-04-27 13:42:12.717  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  79  <<<<<
2021-04-27 13:42:12.717  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  80  <<<<<
2021-04-27 13:42:12.717  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  81  <<<<<
2021-04-27 13:42:12.717  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  82  <<<<<
2021-04-27 13:42:12.717  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  83  <<<<<
2021-04-27 13:42:12.717  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  84  <<<<<
2021-04-27 13:42:12.717  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  85  <<<<<
2021-04-27 13:42:12.717  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  86  <<<<<
2021-04-27 13:42:12.717  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  87  <<<<<
2021-04-27 13:42:12.717  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  88  <<<<<
2021-04-27 13:42:12.717  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  89  <<<<<
2021-04-27 13:42:12.717  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  90  <<<<<
2021-04-27 13:42:12.717  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  91  <<<<<
2021-04-27 13:42:12.717  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  92  <<<<<
2021-04-27 13:42:12.717  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  93  <<<<<
2021-04-27 13:42:12.717  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  94  <<<<<
2021-04-27 13:42:12.717  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  95  <<<<<
2021-04-27 13:42:12.717  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  96  <<<<<
2021-04-27 13:42:12.717  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  97  <<<<<
2021-04-27 13:42:12.717  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  98  <<<<<
2021-04-27 13:42:12.718  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  99  <<<<<
2021-04-27 13:42:12.718  INFO 27484 --- [  restartedMain] b.p.job.SimpleJobConfiguration002        : >>>>>  100  <<<<<
2021-04-27 13:42:12.727  INFO 27484 --- [  restartedMain] o.s.batch.core.step.AbstractStep         : Step: [simpleStep1] executed in 27ms
2021-04-27 13:42:12.735  INFO 27484 --- [  restartedMain] o.s.b.c.l.support.SimpleJobLauncher      : Job: [SimpleJob: [name=simpleJob1]] completed with the following parameters: [{}] and the following status: [COMPLETED] in 42ms

 

사실 1개의 step에서 for문을 이용하여 1~100까지 출력하는 방식이 아니라

job이 작동하면 step을 100개 생성해서 각각 1~100까지 출력하게 만들고 싶었다.

이 생각이 틀렸는지 더 공부해서 만약 가능하다면 시도해봐야겠다!!

제곧내...

 


<update id="companyBoardCountUpadate" parameterType="CompanyBoardContent">
	<selectKey order="BEFORE" keyProperty="companyCount" resultType="String">		
		SELECT 
			c.company_count+1
			from
				tb_company AS c
			where
				c.company_code = #{companyCode}
	</selectKey>
    
    UPDATE tb_company
    	SET
    		company_count= #{companyCount}
    	WHERE 
    		company_code = #{companyCode}
            
</update>

쿼리문도 전부 정상이고 오탈자도 없으며,, DTO에 알맞은 getter, setter도 전부 있었는데!!!!!!!!!!!

org.apache.ibatis.executor.ExecutorException: No setter found for the keyProperty 'companyCount' in java.lang.String.

이 오류로 인해 진행이 안되는 상황이었다..

조언도 구해봤는데 원인을 전혀 모르겠어서 서브쿼리로 처리했다...

마이바티스!!!!!! 나는 너를 믿었는데!! 

 

그래도 서브쿼리로 바꾼 코드가 더 간결해서 기분이 좋아졌다 ~~ ^^~!!

<update id="companyBoardCountUpadate" parameterType="CompanyBoardContent">
	UPDATE tb_company
		SET
			company_count= (SELECT company_count +1)
		WHERE 
			company_code = #{companyCode}
</update>

 

'SpringBoot' 카테고리의 다른 글

[SpringBoot] Batch study...!  (0) 2021.04.28
[SpringBoot] Batch  (0) 2021.04.27
[mybatis] multiple select key  (0) 2020.06.23
파일 업로드  (0) 2020.06.19
<!-- 처리업무 등록 -->
	<insert id="unpaidInsert" parameterType="Unpaid">
		
		<!-- unpaidCode -->
		<selectKey order="BEFORE" keyProperty="unpaidCode" resultType="String">
			select
				(case count(*)
				when 0 then 'unpaid_1'
				else CONCAT('unpaid_',max(cast(substring(unpaid_code,8) as decimal))+1)
				end) as unpaidCode
			from
				tb_unpaid
		</selectKey>
		<selectKey order="BEFORE" keyProperty="customerCode" resultType="String">
			SELECT
				c.customer_code
			from
				tb_customer AS c
				where
					#{customerName} = c.customer_name
					and
					#{customerTel} = c.customer_tel
		</selectKey>
		<selectKey order="BEFORE" keyProperty="unpaidRegStaffCode" resultType="String">
			SELECT
				sf.staff_code
			from
				tb_staff as sf
				join
				tb_member as m
				on
				sf.member_id = m.member_id
				join
				tb_store AS sr
				on
				sf.store_code =sr.store_code
			where
				#{unpaidRegMemberName} = m.member_name
				and
				#{unpaidRegStoreName} = sr.store_name	
		</selectKey>

		INSERT INTO tb_unpaid
			(unpaid_code
			, unpaid_exp_date
			, unpaid_part
			, unpaid_sub_name
			, unpaid_desc
			, customer_code
			, unpaid_memo
			, unpaid_status
			, unpaid_reg_date
			, unpaid_reg_staff_code)
		VALUES 
			(#{unpaidCode}
			, NOW()
			, #{unpaidPart}
			, #{unpaidSubName}
			, #{unpaidDesc}
			, #{customerCode}
			, #{unpaidMemo}
			, #{unpaidStatus}
			, NOW()
			, #{unpaidRegStaffCode})

	</insert>

mapper.xml 에서 <insert></insert> 안에 <selectKey></selectKey>를 여러개 사용하여 여러가지의 조인 값을 가져오고싶었다! 하지만 계속 오류가 발생했다.

알고보니 <selectKey></selectKey> 는 한개만 사용할 수 있다고 한다!!


<!-- 처리업무 등록 -->
	<insert id="unpaidInsert" parameterType="Unpaid">
		<selectKey order="BEFORE" keyProperty="unpaidCode,customerCode,unpaidRegStaffCode" resultType="Map">
			select
				(case count(*)
				when 0 then 'unpaid_1'
				else CONCAT('unpaid_',max(cast(substring(unpaid_code,8) as decimal))+1)
				end) as unpaidCode
				,tc.customer_code as customerCode
				,tc.staff_code as unpaidRegStaffCode
			from
				tb_unpaid AS u ,(
							SELECT
								c.customer_code,
								tf.staff_code
							from
								tb_customer AS c,
								(
								SELECT
								sf.staff_code
								from
									tb_staff as sf
									join
									tb_member as m
									on
									sf.member_id = m.member_id
									join
									tb_store AS sr
									on
									sf.store_code =sr.store_code
								where
									#{unpaidRegMemberName} = m.member_name
									and
									#{unpaidRegStoreName} = sr.store_name
									)AS tf
			where
				#{customerName} = c.customer_name
				and
				#{customerTel} = c.customer_tel
				)AS tc
		</selectKey>

		INSERT INTO tb_unpaid
			(unpaid_code
			, unpaid_exp_date
			, unpaid_part
			, unpaid_sub_name
			, unpaid_desc
			, customer_code
			, unpaid_memo
			, unpaid_status
			, unpaid_reg_date
			, unpaid_reg_staff_code)
		VALUES 
			(#{unpaidCode}
			, NOW()
			, #{unpaidPart}
			, #{unpaidSubName}
			, #{unpaidDesc}
			, #{customerCode}
			, #{unpaidMemo}
			, #{unpaidStatus}
			, NOW()
			, #{unpaidRegStaffCode})
	</insert>

그래서 서브쿼리를 사용하여 여러개의 컬럼을 한개의 selectKey에 담았다.

insert 쿼리문에서 값을 받을 때 #{paramater}와 selectKey의 select문의 alias가 대응된다~!!


친구랑 대화하다보니 하나의 서비스에서 처리하지 않고 서비스를 나누어서 처리하는 방법도 있을 거라고 깨달았다!!

서비스를 나누어 처리하면 서브쿼리를 쓰지 않고도 처리할 수 있을 것이다.

서비스를 하나로 만들면 서비스를 나눈 것 보다 유지보수 측면에서 이득이라고 하니 상황에 따라 골라서 사용해야겠다.

또, 요즘 join이 없도록 작업하는 추세라고 하는데!!

정규화를 막 배운 입장에서는 아직 실제로 사용하기에는 정규화가 마음에 걸린다...

하지만 서브쿼리 안에!! 서브쿼리 안에!! 서브쿼리를 넣다 보니 join이 없는 작업이 더 편리할 것 같다고 느꼈다.

지금 하고있는 프로젝트는 작은 규모이기 때문에 데이터베이스에 데이터가 적어서 체감을 못했지만, join이 많이 일어나면  데이터가 많이 존재할 경우 처리속도가 느려진다고 하니 참고해야겠다!!

 

 

 

+ Recent posts