![](/img/trans.png)
[英]Spring Boot 2.7.1 with Data R2DBC findById() fails when using H2 with MSSQLSERVER compatibility (bad grammar LIMIT 2)
[英]R2dbc H2 issues when using inMemory database
我試圖品嘗 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..."));
}
}
如果我在ConnectionFactory
bean 定義中使用.inMemory("testdb")
,當 Spring ApplicationContext
被初始化時,它失敗了,因為在初始化DataInitializer
時找不到表POSTS
。 從啟動日志來看, ConnectionFactoryInitializer
初始化成功,並通過執行schema.sql 和data.sql 創建了表POSTS並按預期插入了數據。
但是切換到使用.file("./testdb")
,它起作用了。
完整的代碼在這里。
來自官方文檔
@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,這是數據庫交互和 Repository 實現所必需的。
我寫了一個博客張貼有關如何設置開始使用R2DBC開始在這里。 這是使用 H2 數據庫的示例
我的猜測是您沒有正確初始化連接工廠,因此沒有獲得正確的 DatabaseClient。
我從 Spring Data R2dc 開發人員@mp911de 那里得到了答案。 見#issue269
該問題與 H2 在最后一個連接關閉時關閉數據庫的行為有關。 請配置 DB_CLOSE_DELAY=-1 選項,以便 H2 保留數據庫。 或者,使用 H2ConnextionFactory.inMemory(...) 工廠方法創建不依賴於使用中連接計數的 Closeable 連接工廠。
將我的代碼更改為以下內容,它有效:
public ConnectionFactory connectionFactory() {
return H2ConnectionFactory.inMemory("testdb");
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.