我尝试使用嵌入式 H2 数据库来体验 R2dbc,方法如下:
public ConnectionFactory connectionFactory() {
//ConnectionFactory factory = ConnectionFactories.get("r2dbc:h2:mem:///test?options=DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE");
return new H2ConnectionFactory(
H2ConnectionConfiguration.builder()
//.inMemory("testdb")
.file("./testdb")
.username("user")
.password("password").build()
);
}
我定义了一个Bean来创建表格和初始化数据。
@Bean
public ConnectionFactoryInitializer initializer(ConnectionFactory connectionFactory) {
ConnectionFactoryInitializer initializer = new ConnectionFactoryInitializer();
initializer.setConnectionFactory(connectionFactory);
CompositeDatabasePopulator populator = new CompositeDatabasePopulator();
populator.addPopulators(new ResourceDatabasePopulator(new ClassPathResource("schema.sql")));
populator.addPopulators(new ResourceDatabasePopulator(new ClassPathResource("data.sql")));
initializer.setDatabasePopulator(populator);
return initializer;
}
我还定义了另一个组件来通过Java代码设置数据。
@Component
@Slf4j
class DataInitializer {
private final DatabaseClient databaseClient;
public DataInitializer(DatabaseClient databaseClient) {
this.databaseClient = databaseClient;
}
@EventListener(value = ContextRefreshedEvent.class)
public void init() {
log.info("start data initialization ...");
this.databaseClient.insert()
.into("posts")
//.nullValue("id", Integer.class)
.value("title", "First post title")
.value("content", "Content of my first post")
.map((r, m) -> r.get("id", Integer.class))
.all()
.log()
.thenMany(
this.databaseClient.select()
.from("posts")
.orderBy(Sort.by(desc("id")))
.as(Post.class)
.fetch()
.all()
.log()
)
.subscribe(null, null, () -> log.info("initialization done..."));
}
}
如果我在ConnectionFactory
bean定义中使用了.inMemory("testdb")
,当Spring ApplicationContext
初始化时,会因为在初始化DataInitializer
时找不到表格POSTS
而失败。从启动日志中可以看到,ConnectionFactoryInitializer
已经成功初始化,并执行了schema.sql和data.sql以创建表格POSTS并插入数据。
但是,如果改用.file("./testdb")
,则可以正常工作。
完整的代码在这里。
ConnectionFactory
是正常的,ConnectionFactoryInitializer
成功初始化(创建并插入数据),但是当初始化DataInitializer
以插入另一个数据时,由于找不到“posts”表而失败。我提到使用.file("./testdb")
而不是InMemory
,它可以工作。 - Hantsy