diff --git a/spring-batch/src/main/java/com/example/springbatch/application/job/CreateArticleJobConfig.java b/spring-batch/src/main/java/com/example/springbatch/application/job/CreateArticleJobConfig.java index 5ecdbb1b..25f4f7ed 100644 --- a/spring-batch/src/main/java/com/example/springbatch/application/job/CreateArticleJobConfig.java +++ b/spring-batch/src/main/java/com/example/springbatch/application/job/CreateArticleJobConfig.java @@ -3,8 +3,7 @@ package com.example.springbatch.application.job; import com.example.springbatch.application.job.param.CreateArticleJobParam; import com.example.springbatch.application.model.ArticleModel; import com.example.springbatch.domain.entity.Article; -import com.example.springbatch.repository.ArticleRepository; -import lombok.RequiredArgsConstructor; +import com.example.springbatch.domain.repository.ArticleRepository; import lombok.extern.slf4j.Slf4j; import org.springframework.batch.core.Job; import org.springframework.batch.core.Step; @@ -17,32 +16,53 @@ import org.springframework.batch.item.ItemProcessor; import org.springframework.batch.item.ItemWriter; import org.springframework.batch.item.data.RepositoryItemWriter; import org.springframework.batch.item.data.builder.RepositoryItemWriterBuilder; +import org.springframework.batch.item.database.builder.JdbcBatchItemWriterBuilder; +import org.springframework.batch.item.database.builder.JpaItemWriterBuilder; import org.springframework.batch.item.file.FlatFileItemReader; import org.springframework.batch.item.file.builder.FlatFileItemReaderBuilder; import org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; import org.springframework.jdbc.core.JdbcTemplate; +import javax.persistence.EntityManagerFactory; +import javax.sql.DataSource; import java.time.LocalDateTime; -import java.util.List; @Configuration @Slf4j -@RequiredArgsConstructor public class CreateArticleJobConfig { private final JobBuilderFactory jobBuilderFactory; private final StepBuilderFactory stepBuilderFactory; private final ArticleRepository articleRepository; private final CreateArticleJobParam createArticleJobParam; - private final JdbcTemplate jdbcTemplate; + private final JdbcTemplate demoJdbcTemplate; + private final EntityManagerFactory demoEntityManagerFactory; + private final DataSource demoDataSource; + + public CreateArticleJobConfig(JobBuilderFactory jobBuilderFactory, + StepBuilderFactory stepBuilderFactory, + ArticleRepository articleRepository, + CreateArticleJobParam createArticleJobParam, + @Qualifier("demoJdbcTemplate") JdbcTemplate demoJdbcTemplate, + @Qualifier("demoEntityManagerFactory") EntityManagerFactory demoEntityManagerFactory, + DataSource demoDataSource) { + this.jobBuilderFactory = jobBuilderFactory; + this.stepBuilderFactory = stepBuilderFactory; + this.articleRepository = articleRepository; + this.createArticleJobParam = createArticleJobParam; + this.demoJdbcTemplate = demoJdbcTemplate; + this.demoEntityManagerFactory = demoEntityManagerFactory; + this.demoDataSource = demoDataSource; + } @Bean public Job createArticleJob() { return jobBuilderFactory.get("createArticleJob") -// .incrementer(new RunIdIncrementer()) + .incrementer(new RunIdIncrementer()) .start(createArticleStep()) .build(); } @@ -85,7 +105,7 @@ public class CreateArticleJobConfig { // JDBC @Bean public ItemWriter
createArticleWriterJDBC() { - return articles -> jdbcTemplate.batchUpdate("insert into Article (title, content, createdAt) values (?, ?, ?)", + return articles -> demoJdbcTemplate.batchUpdate("insert into Article (title, content, createdAt) values (?, ?, ?)", articles, 1000, (ps, article) -> { @@ -103,4 +123,21 @@ public class CreateArticleJobConfig { .build(); } + // ====================== + +// // JDBC +// @Bean +// public ItemWriter
writerJDBC() { +// return new JdbcBatchItemWriterBuilder
() +// .dataSource(demoDataSource) +// .build(); +// } + + // JPA + @Bean + public ItemWriter
writerJPA() { + return new JpaItemWriterBuilder
() + .entityManagerFactory(this.demoEntityManagerFactory) + .build(); + } } diff --git a/spring-batch/src/main/java/com/example/springbatch/repository/ArticleRepository.java b/spring-batch/src/main/java/com/example/springbatch/domain/repository/ArticleRepository.java similarity index 83% rename from spring-batch/src/main/java/com/example/springbatch/repository/ArticleRepository.java rename to spring-batch/src/main/java/com/example/springbatch/domain/repository/ArticleRepository.java index d517c89f..41e87ebd 100644 --- a/spring-batch/src/main/java/com/example/springbatch/repository/ArticleRepository.java +++ b/spring-batch/src/main/java/com/example/springbatch/domain/repository/ArticleRepository.java @@ -1,4 +1,4 @@ -package com.example.springbatch.repository; +package com.example.springbatch.domain.repository; import com.example.springbatch.domain.entity.Article; import org.springframework.data.jpa.repository.JpaRepository; diff --git a/spring-batch/src/main/java/com/example/springbatch/infrastructure/BatchDataManagerConfig.java b/spring-batch/src/main/java/com/example/springbatch/infrastructure/BatchDataManagerConfig.java new file mode 100644 index 00000000..6cee0e6d --- /dev/null +++ b/spring-batch/src/main/java/com/example/springbatch/infrastructure/BatchDataManagerConfig.java @@ -0,0 +1,22 @@ +package com.example.springbatch.infrastructure; + +import org.springframework.batch.core.configuration.annotation.DefaultBatchConfigurer; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Configuration; +import org.springframework.transaction.PlatformTransactionManager; + +@Configuration +public class BatchDataManagerConfig extends DefaultBatchConfigurer { + + private final PlatformTransactionManager batchTransactionManager; + + public BatchDataManagerConfig( + @Qualifier("batchTransactionManager") PlatformTransactionManager batchTransactionManager) { + this.batchTransactionManager = batchTransactionManager; + } + + @Override + public PlatformTransactionManager getTransactionManager() { + return this.batchTransactionManager; + } +} diff --git a/spring-batch/src/main/java/com/example/springbatch/infrastructure/BatchDataSourceConfig.java b/spring-batch/src/main/java/com/example/springbatch/infrastructure/BatchDataSourceConfig.java new file mode 100644 index 00000000..6e65058c --- /dev/null +++ b/spring-batch/src/main/java/com/example/springbatch/infrastructure/BatchDataSourceConfig.java @@ -0,0 +1,30 @@ +package com.example.springbatch.infrastructure; + +import com.zaxxer.hikari.HikariDataSource; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.jdbc.DataSourceBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; +import org.springframework.transaction.PlatformTransactionManager; + +import javax.sql.DataSource; + +@Configuration +public class BatchDataSourceConfig { + + @Bean + @Primary + @ConfigurationProperties(prefix = "spring.datasource.hikari.batch") + public DataSource batchDataSource() { + return DataSourceBuilder.create().type(HikariDataSource.class).build(); + } + + @Bean + public PlatformTransactionManager batchTransactionManager ( + @Qualifier("batchDataSource") DataSource batchDataSource) { + return new DataSourceTransactionManager(batchDataSource); + } +} diff --git a/spring-batch/src/main/java/com/example/springbatch/infrastructure/DemoDataManagerConfig.java b/spring-batch/src/main/java/com/example/springbatch/infrastructure/DemoDataManagerConfig.java new file mode 100644 index 00000000..eeb04f86 --- /dev/null +++ b/spring-batch/src/main/java/com/example/springbatch/infrastructure/DemoDataManagerConfig.java @@ -0,0 +1,63 @@ +package com.example.springbatch.infrastructure; + +import org.hibernate.cfg.AvailableSettings; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +import javax.sql.DataSource; +import java.util.Properties; + +@Configuration +@EnableTransactionManagement +@EnableJpaRepositories( + basePackages = { + "com.example.springbatch.domain.repository" + }, + entityManagerFactoryRef = "demoEntityManagerFactory", + transactionManagerRef = "demoTransactionManager" +) +public class DemoDataManagerConfig { + + private final DataSource dataSource; + + public DemoDataManagerConfig( + @Qualifier("demoDataSource") DataSource dataSource) { + this.dataSource = dataSource; + } + + @Bean + public LocalContainerEntityManagerFactoryBean demoEntityManagerFactory() { + LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); + HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); + vendorAdapter.setGenerateDdl(true); + + em.setDataSource(this.dataSource); + em.setPersistenceUnitName("demoEntityManager"); + em.setPackagesToScan( + "com.example.springbatch.domain.entity" + ); + em.setJpaVendorAdapter(vendorAdapter); + em.setJpaProperties(demoJpaProperties()); + em.afterPropertiesSet(); + return em; + } + + @Bean + public JdbcTemplate demoJdbcTemplate(@Qualifier("demoDataSource") DataSource dataSource) { + return new JdbcTemplate(dataSource); + } + + private Properties demoJpaProperties() { + Properties properties = new Properties(); + properties.setProperty(AvailableSettings.HBM2DDL_AUTO, "update"); + properties.setProperty(AvailableSettings.SHOW_SQL, "true"); + properties.setProperty(AvailableSettings.ALLOW_UPDATE_OUTSIDE_TRANSACTION, "true"); + return properties; + } +} diff --git a/spring-batch/src/main/java/com/example/springbatch/infrastructure/DemoDataSourceConfig.java b/spring-batch/src/main/java/com/example/springbatch/infrastructure/DemoDataSourceConfig.java new file mode 100644 index 00000000..e832289a --- /dev/null +++ b/spring-batch/src/main/java/com/example/springbatch/infrastructure/DemoDataSourceConfig.java @@ -0,0 +1,31 @@ +package com.example.springbatch.infrastructure; + +import com.zaxxer.hikari.HikariDataSource; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.jdbc.DataSourceBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.transaction.PlatformTransactionManager; + +import javax.persistence.EntityManagerFactory; +import javax.sql.DataSource; + +@Configuration +public class DemoDataSourceConfig { + + @Bean + @ConfigurationProperties(prefix = "spring.datasource.hikari.demo") + public DataSource demoDataSource() { + return DataSourceBuilder.create().type(HikariDataSource.class).build(); + } + + @Bean + public PlatformTransactionManager demoTransactionManager( + @Qualifier("demoEntityManagerFactory") EntityManagerFactory demoEntityManagerFactory) { + JpaTransactionManager demoTransactionManager = new JpaTransactionManager(); + demoTransactionManager.setEntityManagerFactory(demoEntityManagerFactory); + return demoTransactionManager; + } +} diff --git a/spring-batch/src/main/resources/application-local.yml b/spring-batch/src/main/resources/application-local.yml index 507815f3..f60a50a3 100644 --- a/spring-batch/src/main/resources/application-local.yml +++ b/spring-batch/src/main/resources/application-local.yml @@ -1,13 +1,25 @@ spring: datasource: - url: jdbc:mysql://localhost:3306/batch?rewriteBatchedStatements=true - username: batch - password: 1234 + # 데이터베이스 분리 방법 (2) + hikari: + batch: + jdbc-url: jdbc:mysql://localhost:3306/batch + driver-class-name: com.mysql.cj.jdbc.Driver + username: batch + password: 1234 + demo: + jdbc-url: jdbc:mysql://localhost:3306/demo?rewriteBatchedStatements=true + driver-class-name: com.mysql.cj.jdbc.Driver + username: batch + password: 1234 + batch: initialize-schema: always job: names: ${job.name:createArticleJob} - +# # 데이터베이스 분리 방법 (1) +# schema: schema-mysql.sql +# table-prefix: batch.BATCH_ jpa: generate-ddl: true hibernate: