[SPRING] 스프링 배치 데이터와 비즈니스 데이터를위한 별도의 데이터 소스를 java-configure하는 방법은 무엇입니까? 심지어해야합니까?
SPRING스프링 배치 데이터와 비즈니스 데이터를위한 별도의 데이터 소스를 java-configure하는 방법은 무엇입니까? 심지어해야합니까?
저의 주요 업무는 읽기 작업 만하고 다른 하나는 작문을하지만 트랜잭션을 무시하는 MyISAM 엔진에서는 트랜잭션 지원이 필요하지 않습니다. Spring Batch가 비즈니스 데이터를 보유하고있는 JobRepository와는 별도의 자체 데이터 소스를 갖도록 어떻게 구성 할 수 있습니까? 초기 데이터 소스 설정은 다음과 같이 이루어집니다 :
@Configuration
public class StandaloneInfrastructureConfiguration {
@Autowired
Environment env;
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource());
em.setPackagesToScan(new String[] { "org.podcastpedia.batch.*" });
JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(additionalJpaProperties());
return em;
}
Properties additionalJpaProperties() {
Properties properties = new Properties();
properties.setProperty("hibernate.hbm2ddl.auto", "none");
properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
properties.setProperty("hibernate.show_sql", "true");
return properties;
}
@Bean
public DataSource dataSource(){
return DataSourceBuilder.create()
.url(env.getProperty("db.url"))
.driverClassName(env.getProperty("db.driver"))
.username(env.getProperty("db.username"))
.password(env.getProperty("db.password"))
.build();
}
@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf){
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(emf);
return transactionManager;
}
}
@EnableBatchProcessing 어노테이션이이를 자동으로 사용하는 Job 구성 클래스에 가져옵니다. 내 생각 엔 DefaultBatchConfigurer를 확장하는 구성 클래스를 설정하려고했지만 그 다음에는
@Configuration
@EnableBatchProcessing
@Import({StandaloneInfrastructureConfiguration.class, NotifySubscribersServicesConfiguration.class})
public class NotifySubscribersJobConfiguration extends DefaultBatchConfigurer {
@Autowired
private JobBuilderFactory jobBuilders;
@Autowired
private StepBuilderFactory stepBuilders;
@Autowired
private DataSource dataSource;
@Autowired
Environment env;
@Override
@Autowired
public void setDataSource(javax.sql.DataSource dataSource) {
super.setDataSource(batchDataSource());
}
private DataSource batchDataSource(){
return DataSourceBuilder.create()
.url(env.getProperty("batchdb.url"))
.driverClassName(env.getProperty("batchdb.driver"))
.username(env.getProperty("batchdb.username"))
.password(env.getProperty("batchdb.password"))
.build();
}
@Bean
public ItemReader<User> notifySubscribersReader(){
JdbcCursorItemReader<User> reader = new JdbcCursorItemReader<User>();
String sql = "select * from users where is_email_subscriber is not null";
reader.setSql(sql);
reader.setDataSource(dataSource);
reader.setRowMapper(rowMapper());
return reader;
}
........
}
어떤 생각이라도 환영받는 것 이상입니다. 이 프로젝트는 GitHub에서 사용할 수 있습니다 - https://github.com/podcastpedia/podcastpedia-batch
무리 감사.
해결법
-
==============================
1.좋아, 이것은 이상하지만 작동한다. 데이터 소스를 자신의 구성 클래스로 옮기는 것만으로도 잘 작동하며 하나는 자동 응답 할 수 있습니다.
좋아, 이것은 이상하지만 작동한다. 데이터 소스를 자신의 구성 클래스로 옮기는 것만으로도 잘 작동하며 하나는 자동 응답 할 수 있습니다.
예제는 스프링 배치 서비스 예제의 다중 데이터 소스 버전입니다.
DataSourceConfiguration :
public class DataSourceConfiguration { @Value("classpath:schema-mysql.sql") private Resource schemaScript; @Bean @Primary public DataSource hsqldbDataSource() throws SQLException { final SimpleDriverDataSource dataSource = new SimpleDriverDataSource(); dataSource.setDriver(new org.hsqldb.jdbcDriver()); dataSource.setUrl("jdbc:hsqldb:mem:mydb"); dataSource.setUsername("sa"); dataSource.setPassword(""); return dataSource; } @Bean public JdbcTemplate jdbcTemplate(final DataSource dataSource) { return new JdbcTemplate(dataSource); } @Bean public DataSource mysqlDataSource() throws SQLException { final SimpleDriverDataSource dataSource = new SimpleDriverDataSource(); dataSource.setDriver(new com.mysql.jdbc.Driver()); dataSource.setUrl("jdbc:mysql://localhost/spring_batch_example"); dataSource.setUsername("test"); dataSource.setPassword("test"); DatabasePopulatorUtils.execute(databasePopulator(), dataSource); return dataSource; } @Bean public JdbcTemplate mysqlJdbcTemplate(@Qualifier("mysqlDataSource") final DataSource dataSource) { return new JdbcTemplate(dataSource); } private DatabasePopulator databasePopulator() { final ResourceDatabasePopulator populator = new ResourceDatabasePopulator(); populator.addScript(schemaScript); return populator; } }
배치 구성 :
@Configuration @EnableBatchProcessing @Import({ DataSourceConfiguration.class, MBeanExporterConfig.class }) public class BatchConfiguration { @Autowired private JobBuilderFactory jobs; @Autowired private StepBuilderFactory steps; @Bean public ItemReader<Person> reader() { final FlatFileItemReader<Person> reader = new FlatFileItemReader<Person>(); reader.setResource(new ClassPathResource("sample-data.csv")); reader.setLineMapper(new DefaultLineMapper<Person>() { { setLineTokenizer(new DelimitedLineTokenizer() { { setNames(new String[] { "firstName", "lastName" }); } }); setFieldSetMapper(new BeanWrapperFieldSetMapper<Person>() { { setTargetType(Person.class); } }); } }); return reader; } @Bean public ItemProcessor<Person, Person> processor() { return new PersonItemProcessor(); } @Bean public ItemWriter<Person> writer(@Qualifier("mysqlDataSource") final DataSource dataSource) { final JdbcBatchItemWriter<Person> writer = new JdbcBatchItemWriter<Person>(); writer.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<Person>()); writer.setSql("INSERT INTO people (first_name, last_name) VALUES (:firstName, :lastName)"); writer.setDataSource(dataSource); return writer; } @Bean public Job importUserJob(final Step s1) { return jobs.get("importUserJob").incrementer(new RunIdIncrementer()).flow(s1).end().build(); } @Bean public Step step1(final ItemReader<Person> reader, final ItemWriter<Person> writer, final ItemProcessor<Person, Person> processor) { return steps.get("step1") .<Person, Person> chunk(1) .reader(reader) .processor(processor) .writer(writer) .build(); } }
-
==============================
2.데이터 소스는 별도의 구성 클래스에 있습니다. 배치 구성에서 DefaultBatchConfigurer를 확장하고 setDataSource 메소드를 재정 의하여 Spring Batch와 함께 @Qualifier와 함께 사용할 특정 데이터베이스를 전달합니다. 이 생성자 버전을 사용하여 작동시키지 못했습니다,하지만 setter 메서드를 나를 위해 일했다.
데이터 소스는 별도의 구성 클래스에 있습니다. 배치 구성에서 DefaultBatchConfigurer를 확장하고 setDataSource 메소드를 재정 의하여 Spring Batch와 함께 @Qualifier와 함께 사용할 특정 데이터베이스를 전달합니다. 이 생성자 버전을 사용하여 작동시키지 못했습니다,하지만 setter 메서드를 나를 위해 일했다.
My Reader, Processor 및 Writer 's는 단계와 함께 자체 포함 된 클래스에 있습니다.
이것은 Spring Boot 1.1.8과 Spring Batch 3.0.1을 사용하고 있습니다. 참고 : 우리는 새로운 버전에서 동일하게 작동하지 않는 Spring Boot 1.1.5를 사용하는 프로젝트에 대해 다른 설정을했습니다.
package org.sample.config.jdbc; import javax.sql.DataSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.core.env.Environment; import com.atomikos.jdbc.AtomikosDataSourceBean; import com.mysql.jdbc.jdbc2.optional.MysqlXADataSource; /** * The Class DataSourceConfiguration. * */ @Configuration public class DataSourceConfig { private final static Logger log = LoggerFactory.getLogger(DataSourceConfig.class); @Autowired private Environment env; /** * Siphon data source. * * @return the data source */ @Bean(name = "mainDataSource") @Primary public DataSource mainDataSource() { final String user = this.env.getProperty("db.main.username"); final String password = this.env.getProperty("db.main.password"); final String url = this.env.getProperty("db.main.url"); return this.getMysqlXADataSource(url, user, password); } /** * Batch data source. * * @return the data source */ @Bean(name = "batchDataSource", initMethod = "init", destroyMethod = "close") public DataSource batchDataSource() { final String user = this.env.getProperty("db.batch.username"); final String password = this.env.getProperty("db.batch.password"); final String url = this.env.getProperty("db.batch.url"); return this.getAtomikosDataSource("metaDataSource", this.getMysqlXADataSource(url, user, password)); } /** * Gets the mysql xa data source. * * @param url the url * @param user the user * @param password the password * @return the mysql xa data source */ private MysqlXADataSource getMysqlXADataSource(final String url, final String user, final String password) { final MysqlXADataSource mysql = new MysqlXADataSource(); mysql.setUser(user); mysql.setPassword(password); mysql.setUrl(url); mysql.setPinGlobalTxToPhysicalConnection(true); return mysql; } /** * Gets the atomikos data source. * * @param resourceName the resource name * @param xaDataSource the xa data source * @return the atomikos data source */ private AtomikosDataSourceBean getAtomikosDataSource(final String resourceName, final MysqlXADataSource xaDataSource) { final AtomikosDataSourceBean atomikos = new AtomikosDataSourceBean(); atomikos.setUniqueResourceName(resourceName); atomikos.setXaDataSource(xaDataSource); atomikos.setMaxLifetime(3600); atomikos.setMinPoolSize(2); atomikos.setMaxPoolSize(10); return atomikos; } } package org.sample.settlement.batch; import javax.sql.DataSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.batch.core.Job; import org.springframework.batch.core.Step; import org.springframework.batch.core.configuration.annotation.DefaultBatchConfigurer; import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; import org.springframework.batch.core.configuration.annotation.JobBuilderFactory; import org.springframework.batch.core.configuration.annotation.StepBuilderFactory; import org.springframework.batch.core.launch.support.RunIdIncrementer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.transaction.PlatformTransactionManager; /** * The Class BatchConfiguration. * */ @Configuration @EnableBatchProcessing public class BatchConfiguration extends DefaultBatchConfigurer { private final static Logger log = LoggerFactory.getLogger(BatchConfiguration.class); @Autowired private JobBuilderFactory jobs; @Autowired private StepBuilderFactory steps; @Autowired private PlatformTransactionManager transactionManager; @Autowired @Qualifier("processStep") private Step processStep; /** * Process payments job. * * @return the job */ @Bean(name = "processJob") public Job processJob() { return this.jobs.get("processJob") .incrementer(new RunIdIncrementer()) .start(processStep) .build(); } @Override @Autowired public void setDataSource(@Qualifier("batchDataSource") DataSource batchDataSource) { super.setDataSource(batchDataSource); } }
-
==============================
3.이런 식으로 이미 시도해 봤니?
이런 식으로 이미 시도해 봤니?
@Bean(name="batchDataSource") public DataSource batchDataSource(){ return DataSourceBuilder.create() .url(env.getProperty("batchdb.url")) .driverClassName(env.getProperty("batchdb.driver")) .username(env.getProperty("batchdb.username")) .password(env.getProperty("batchdb.password")) .build(); }
다른 데이터 소스를 @Primary로 표시하고 배치 구성에서 @Qualifier를 사용하여 batchDataSource bean을 와이어 링하도록 지정하십시오.
-
==============================
4.https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-two-datasources의 경우 :
https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-two-datasources의 경우 :
@Bean @Primary @ConfigurationProperties("app.datasource.first") public DataSourceProperties firstDataSourceProperties() { return new DataSourceProperties(); } @Bean @Primary @ConfigurationProperties("app.datasource.first") public DataSource firstDataSource() { return firstDataSourceProperties().initializeDataSourceBuilder().build(); } @Bean @ConfigurationProperties("app.datasource.second") public DataSourceProperties secondDataSourceProperties() { return new DataSourceProperties(); } @Bean @ConfigurationProperties("app.datasource.second") public DataSource secondDataSource() { return secondDataSourceProperties().initializeDataSourceBuilder().build(); }
응용 프로그램 속성에서 일반 데이터 소스 속성을 사용할 수 있습니다.
app.datasource.first.type=com.zaxxer.hikari.HikariDataSource app.datasource.first.maximum-pool-size=30 app.datasource.second.url=jdbc:mysql://localhost/test app.datasource.second.username=dbuser app.datasource.second.password=dbpass app.datasource.second.max-total=30
-
==============================
5.두 개의 데이터 소스가 있다고 가정하면, 작업 세부 정보와 같은 스프링 배치 메타 데이터 ([CONFIGDB]라고 말하면 됨)와 비즈니스 데이터에 대한 기타 [AppDB]라고합니다.
두 개의 데이터 소스가 있다고 가정하면, 작업 세부 정보와 같은 스프링 배치 메타 데이터 ([CONFIGDB]라고 말하면 됨)와 비즈니스 데이터에 대한 기타 [AppDB]라고합니다.
CONFIGDB를 jobRepository에 다음과 같이 삽입하십시오.
<bean id="jobRepository" class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean"> <property name="transactionManager" ref="transactionManager" /> <property name="dataSource" ref="CONFIGDB" /> <property name="databaseType" value="db2" /> <property name="tablePrefix" value="CONFIGDB.BATCH_" /> </bean>
이제 AppDB 다르 타 소스를 DAO 또는 OR Writer에 삽입 할 수 있습니다.
<bean id="DemoItemWriter" class="com.demoItemWriter"> <property name="dataSource" ref="AppDB" /> </bean>
또는
당신은 리소스를 정의 할 수 있고 클래스에서 jndi lookup으로이 AppDB를 주입한다.
public class ExampleDAO { @Resource(lookup = "java:comp/env/jdbc/AppDB") DataSource ds;
}
from https://stackoverflow.com/questions/25256487/how-to-java-configure-separate-datasources-for-spring-batch-data-and-business-da by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] 스프링 부트에서 @Repository 주석이 달린 인터페이스를 Autowire 할 수 없음 (0) | 2018.12.14 |
---|---|
[SPRING] Spring @Scheduled 주석이 달린 메서드는 다른 스레드에서 실행됩니까? (0) | 2018.12.14 |
[SPRING] @Aspect aspect에 대한 스프링 autowired bean은 null이다. (0) | 2018.12.14 |
[SPRING] 다중 스레드에서 스프링 트랜잭션을 사용하는 방법 (0) | 2018.12.14 |
[SPRING] Spring AOP를 사용하여 메소드 인수를 얻으시겠습니까? (0) | 2018.12.14 |