【发布时间】:2016-01-10 20:37:46
【问题描述】:
上下文
我正在尝试使用 JPA 存储库通过 Spring Boot 开发批处理服务。使用两个不同的数据源,我希望在内存数据库中创建与批处理相关的表,这样它就不会污染我的业务数据库。
根据网络上的多个主题,我想出了我的两个数据源的配置:
@Configuration
public class DataSourceConfiguration {
@Bean(name = "mainDataSource")
@Primary
@ConfigurationProperties(prefix="spring.datasource")
public DataSource mainDataSource(){
return DataSourceBuilder.create().build();
}
@Bean(name = "batchDataSource")
public DataSource batchDataSource( @Value("${batch.datasource.url}") String url ){
return DataSourceBuilder.create().url( url ).build();
}
}
第一个,mainDataSource,使用默认的 Spring 数据库配置。 batchDataSource 定义了一个嵌入式 HSQL 数据库,我希望在其中创建批处理和步骤表。
# DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties)
spring.datasource.url=jdbc:mariadb://localhost:3306/batch_poc
spring.datasource.username=root
spring.datasource.password=
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
spring.datasource.max-age=10000
spring.datasource.initialize=false
# JPA (JpaBaseConfiguration, HibernateJpaAutoConfiguration)
spring.jpa.generate-ddl=false
spring.jpa.show-sql=true
spring.jpa.database=MYSQL
# SPRING BATCH (BatchDatabaseInitializer)
spring.batch.initializer.enabled=false
# ----------------------------------------
# PROJECT SPECIFIC PROPERTIES
# ----------------------------------------
# BATCH DATASOURCE
batch.datasource.url=jdbc:hsqldb:file:C:/tmp/hsqldb/batchdb
这是我的批处理配置:
@Configuration
@EnableBatchProcessing
public class BatchConfiguration {
private static final Logger LOG = Logger.getLogger( BatchConfiguration.class );
@Bean
public BatchConfigurer configurer(){
return new CustomBatchConfigurer();
}
@Bean
public Job importElementsJob( JobBuilderFactory jobs, Step step1 ){
return jobs.get("importElementsJob")
.incrementer( new RunIdIncrementer() )
.flow( step1 )
.end()
.build();
}
@Bean
public Step step1( StepBuilderFactory stepBuilderFactory, ItemReader<InputElement> reader,
ItemWriter<List<Entity>> writer, ItemProcessor<InputElement, List<Entity>> processor ){
return stepBuilderFactory.get("step1")
.<InputElement, List<Entity>> chunk(100)
.reader( reader )
.processor( processor )
.writer( writer )
.build();
}
@Bean
public ItemReader<InputElement> reader() throws IOException {
return new CustomItemReader();
}
@Bean
public ItemProcessor<InputElement, List<Entity>> processor(){
return new CutsomItemProcessor();
}
@Bean
public ItemWriter<List<Entity>> writer(){
return new CustomItemWriter();
}
}
BatchConfigurer,使用内存数据库:
public class CustomBatchConfigurer extends DefaultBatchConfigurer {
@Override
@Autowired
public void setDataSource( @Qualifier("batchDataSource") DataSource dataSource) {
super.setDataSource(dataSource);
}
}
最后,我的作家:
public class CustomItemWriter implements ItemWriter<List<Entity>> {
private static final Logger LOG = Logger.getLogger( EntityWriter.class );
@Autowired
private EntityRepository entityRepository;
@Override
public void write(List<? extends List<Entity>> items)
throws Exception {
if( items != null && !items.isEmpty() ){
for( List<Entity> entities : items ){
for( Entity entity : entities ){
Entity fromDb = entityRepository.findById( entity.getId() );
// Insert
if( fromDb == null ){
entityRepository.save( entity );
}
// Update
else {
// TODO : entityManager.merge()
}
}
}
}
}
}
EntityRepository 接口扩展了 JpaRepository。
问题
当我以这种方式分离数据源时,当我调用存储库的保存方法时没有任何反应。我在日志中看到调用 findById() 的选择查询。但没有什么可以挽救的。最后我的输出数据库是空的。
当我回到一个独特的数据源配置(删除配置器 bean 并让 Spring Boot 单独管理数据源)时,插入查询工作正常。
可能主数据源配置不足以让 JPA 正确执行插入。但是缺少什么?
【问题讨论】:
-
由于您使用两个不同的数据源,您会遇到事务问题吗?两个数据源是否都注册了同一个 TransactionManager?默认情况下,这是上下文中名为“transactionManager”的 bean。 SpringBatch 提交此 TM,如果您的 Datasource 未在此处注册,它将永远不会收到提交。
-
我想我遇到了 transactionManager 问题,是的。通过下面发布的解决方案,我使用 Spring 创建的 EntityManagerFactory bean 定义了自己的 JpaTransactionManager,它可以工作。
标签: spring jpa spring-boot spring-batch