具有多个数据源的春季批处理junit。 spring data jpa无法将数据保存在内存数据库中
Posted
技术标签:
【中文标题】具有多个数据源的春季批处理junit。 spring data jpa无法将数据保存在内存数据库中【英文标题】:spring batch junit with multiple datasources. spring data jpa unable to save data in-memory database 【发布时间】:2020-07-04 14:30:30 【问题描述】:我的场景是批处理作业应该从 1 个 DB (H2) 读取数据并将数据转储到另一个 DB (postgres)。因此我配置了多个数据源
我已经使用 spring batch 4.2 和 Spring boot 2.2.5.RELEASE 编写了批处理作业。现在我需要为端到端测试编写测试用例。
我已经使用 ResourcelessTransactionManager 使用自定义批处理配置器来避免将批处理表元数据保存在内存和实际数据库中,并且它正在工作。但是,我无法通过调用 readerRepository.save(randomReader); 将业务数据保存在 junit 中的 H2 内存数据库中;如果我在junit中用postgres testconatiner替换H2内存数据库,同样的工作。
存储库测试的示例junit
@Slf4j
@SpringBootTest
@Import(LiquibaseConfigReader.class)
class ReaderRepositoryTest
@Autowired
private ReaderRepository readerRepository;
@BeforeEach
void setUp()
readerRepository.deleteAll();
@Test
void shouldFetchAllRecords()
var randomReader = RandomDataGenerator.randomReader();
assertThat(readerRepository.findAll()).hasSize(0);
readerRepository.save(randomReader);
assertThat(readerRepository.findAll()).hasSize(1);
我无法理解为什么我能够将数据保存在 postgres 测试容器中,但不能保存在内存中的 H2 数据库中在运行 Junit 测试时。
为了将批处理表元数据保存在内存映射中,我尝试了以下解决方案,现在批处理表元数据没有保存在 DB 中的任何位置。但是,如上所述,我开始在 junit 中遇到 spring data jpa 问题。
Java Spring Batch using embedded database for metadata and a second database for other data
Spring boot + spring batch without DataSource
https://github.com/riversoforion/spring-batch-inmem/blob/master/src/main/java/com/example/batch/CustomBatchConfigurer.java
是因为 ResourcelessTransactionManager 吗?如果是,我该如何避免将批处理表元数据保存在任何数据库中,包括内存中。
我已经浏览了这里给出的多个问题,但没有一个能够将业务数据保存在 h2 数据库中。
【问题讨论】:
【参考方案1】:没有您的源代码很难回答。据我所知,您希望有一个数据库来读取来自 (H2) 的数据和一个来写入数据到 (postgres)。
而且您不希望 Spring 批处理将其元数据写入两个数据库。
然后你写,你不明白为什么你不能写到 H2 - 我想,你在这里只指 Spring Batch 元数据。
因此,一个可能的解决方案可能是更改BatchConfigurer
:
...
public class CustomBatchConfigurer extends DefaultBatchConfigurer
@Autowired
@Qualifier("repoDataSource")
private DataSource dataSource;
@Override
protected JobRepository createJobRepository() throws Exception
JobRepositoryFactoryBean factoryBean = new JobRepositoryFactoryBean();
factoryBean.setDatabaseType(DatabaseType.POSTGRES.getProductName());
factoryBean.setTablePrefix("TMP_");
factoryBean.setIsolationLevelForCreate("ISOLATION_REPEATABLE_READ");
factoryBean.setDataSource(this.dataSource);
factoryBean.afterPropertiesSet();
return factoryBean.getObject();
在这里,您在数据源repoDataSource
中自动装配,然后createJobRepository()
被覆盖,DefaultBatchConfigurer
使用它来创建JobRepository
。它不是默认的BATCH_
,而是使用表前缀TMP_
,而不是默认的ISOLATION_SERIALIZED
,事务隔离级别设置为ISOLATION_REPEATABLE_READ
。
Spring 不会直接调用 DefaultBatchConfigurer
中的任何 create
方法作为 bean 定义,因此必须显式调用 InitializingBean
afterPropertiesSet()
和 FactoryBean
getObject()
。
如果您真的不想让 Spring Batch 完成大部分工作并使用元数据帮助批处理管理,那么您的问题可能与 Spring-Batch without persisting metadata to database? 重复。
【讨论】:
我已经用代码更新了我的问题。澄清一下,我无法通过调用 readerRepository.save(randomReader) 将业务数据保存在 junit 中的 H2 内存数据库中;但是,如果我实际上正在运行我的批处理服务,它会将数据保存在同一个内存数据库中。以上是关于具有多个数据源的春季批处理junit。 spring data jpa无法将数据保存在内存数据库中的主要内容,如果未能解决你的问题,请参考以下文章
有没有办法 MySQLMaxValueIncrementer 在春季批处理中连接到多个数据源
在春季批处理(spring-boot-1.5.2.RELEASE)中使用多个数据源在启动时引发异常
Spring Boot / JUnit,为多个配置文件运行所有单元测试