使用inMemory数据库时出现R2dbc H2问题

我试图品尝R2dbc并使用嵌入式H2,例如:

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..."));
    }

}

如果我在.inmemory("testdb") bean定义中使用ConnectionFactory,则在初始化Spring ApplicationContext时失败,因为找不到表POSTS 初始化DataInitializer时。通过启动日志记录,ConnectionFactoryInitializer已成功初始化,并创建表 POSTS 并通过执行schema.sql和data.sql按预期插入数据。

但是切换为使用.file("./testdb")确实有效。

完整的代码是here

wangyi19890218 回答:使用inMemory数据库时出现R2dbc H2问题

摘自官方文档

ConnectionFactory

@Configuration
public class ApplicationConfiguration extends AbstractR2dbcConfiguration {

  @Override
  @Bean
  public ConnectionFactory connectionFactory() {
    return …;
  }
}

这种方法使您可以使用标准的io.r2dbc.spi.ConnectionFactory 例如,使用Spring的容器 AbstractR2dbcConfiguration。与注册一个相比 直接使用ConnectionFactory实例,配置支持有 还为容器提供了一个额外的优势 ExceptionTranslator实现,将R2DBC异常转换为 Spring的可移植DataAccessException层次结构中的数据异常 访问带有@Repository批注的类。

(...)

AbstractR2dbcConfiguration还注册了DatabaseClient,这是数据库交互和存储库实现所必需的。

我写了一篇有关如何设置R2DBC here入门的博客文章。 Here是使用H2数据库的示例

我的猜测是您没有正确初始化连接工厂,因此无法获得正确的DatabaseClient。

,

我从Spring Data R2dc开发人员@ mp911de得到了答案。参见#issue269

该问题与H2在最后一个连接关闭时关闭数据库的行为有关。请配置DB_CLOSE_DELAY = -1选项,以便H2保留数据库。或者,使用H2ConnextionFactory.inMemory(...)工厂方法创建一个不依赖于正在使用的连接数的Closeable连接工厂。

将我的代码更改为以下代码,即可使用:


 public ConnectionFactory connectionFactory() {       
     return H2ConnectionFactory.inMemory("testdb");
 }
本文链接:https://www.f2er.com/2818531.html

大家都在问