如何配置 spring-boot 以使用基于文件的 H2 数据库

How to configure spring-boot to use file based H2 database

我已经成功地创建了一个 spring 启动应用程序,它使用内存中的 H2 嵌入式数据库。我现在想将其更改为将持续存在的基于文件的版本。

我试过只更改 application.properties 文件中的 spring.datasource.* 属性,它们看起来像这样:

spring.datasource.url=jdbc:h2:file:~/test;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.username=test
spring.datasource.password=test
spring.datasource.driverClassName=org.h2.Driver`  

似乎spring boot 只是忽略了这些设置,因为它只是启动如下:

o.s.j.d.e.EmbeddedDatabaseFactory        : Starting embedded database: url='jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false', username='sa'

我的 pom.xml 包含以下可能与此 post 相关的依赖项:

<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>1.3.5.RELEASE</version>
</parent>
....
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency> 
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
</dependency>

我从文档和许多 posts 中了解到配置应该可以正常工作,但对我来说并不走运。只是为了防止一些基本错误,我已经尝试并检查了以下内容:

  1. 我的应用程序属性在类路径中:
  2. 我试图在注释中排除自动配置 @EnableAutoConfiguration
  3. 我尝试使用注释 @Primary@ConfigurationProperties(prefix = "spring.datasource") 的组合注入 dataSource bean,并使用 DataSourceBuilder 以编程方式设置属性。这会导致与 null 类型相关的其他错误。

我好像漏掉了一个关键概念什么的。谁能帮忙。

更新 1:摘自我的自动配置报告:

Positive matches:
-----------------

    DataSourceAutoConfiguration matched
  - @ConditionalOnClass classes found: javax.sql.DataSource,org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType (OnClassCondition)

   DataSourceAutoConfiguration.DataSourceInitializerConfiguration matched
  - @ConditionalOnMissingBean (types: org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer; SearchStrategy: all) found no beans (OnBeanCondition)

   DataSourceAutoConfiguration.EmbeddedConfiguration matched
  - embedded database H2 detected (DataSourceAutoConfiguration.EmbeddedDataSourceCondition)
  - @ConditionalOnMissingBean (types: javax.sql.DataSource,javax.sql.XADataSource; SearchStrategy: all) found no beans (OnBeanCondition)

   DataSourceAutoConfiguration.JdbcTemplateConfiguration matched
  - existing auto database detected (DataSourceAutoConfiguration.DataSourceAvailableCondition)

   DataSourceAutoConfiguration.JdbcTemplateConfiguration#jdbcTemplate matched
  - @ConditionalOnMissingBean (types: org.springframework.jdbc.core.JdbcOperations; SearchStrategy: all) found no beans (OnBeanCondition)

   DataSourceAutoConfiguration.JdbcTemplateConfiguration#namedParameterJdbcTemplate matched
  - @ConditionalOnMissingBean (types: org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations; SearchStrategy: all) found no beans (OnBeanCondition)

   DataSourceTransactionManagerAutoConfiguration matched
  - @ConditionalOnClass classes found: org.springframework.jdbc.core.JdbcTemplate,org.springframework.transaction.PlatformTransactionManager (OnClassCondition)

   DataSourceTransactionManagerAutoConfiguration.TransactionManagementConfiguration matched
  - @ConditionalOnMissingBean (types: org.springframework.transaction.annotation.AbstractTransactionManagementConfiguration; SearchStrategy: all) found no beans (OnBeanCondition)

    H2ConsoleAutoConfiguration matched
  - @ConditionalOnClass classes found: org.h2.server.web.WebServlet (OnClassCondition)
  - found web application StandardServletEnvironment (OnWebApplicationCondition)
  - matched (OnPropertyCondition)

   HibernateJpaAutoConfiguration matched
  - @ConditionalOnClass classes found: org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean,org.springframework.transaction.annotation.EnableTransactionManagement,javax.persistence.EntityManager (OnClassCondition)
  - found HibernateEntityManager class (HibernateJpaAutoConfiguration.HibernateEntityManagerCondition)

Negative matches:
-----------------

    DataSourceAutoConfiguration.NonEmbeddedConfiguration did not match
  - missing supported DataSource (DataSourceAutoConfiguration.NonEmbeddedDataSourceCondition)

`

更新 2:添加了执行器并查看了端点 /configprops。这里有趣的是我的配置已经被采用并且数据库存在但是当应用程序运行时它不使用这个 dataSource.

"spring.datasource.CONFIGURATION_PROPERTIES":
    {"prefix":"spring.datasource",
     "properties":{
        "schema":null,
        "data":null,
        "xa":{"dataSourceClassName":null,
               "properties":{}
             },
        "type":null,
        "separator":";",
        "url":"jdbc:h2:file:~/test;DB_CLOSE_ON_EXIT=FALSE",
        "platform":"all",
        "continueOnError":false,
        "jndiName":null,               
        "sqlScriptEncoding":null,
        "password":"******",
        "name":"testdb",
        "driverClassName":"org.h2.Driver",
        "initialize":true,
        "username":"test"
        }
    }  

在您的 class 路径中创建一个文件 .h2.server.properties 并在下方添加内容并重试。您可以在资源文件夹中创建此文件。

#H2 Server Properties
0=H2 File|org.h2.Driver|jdbc\:h2\:file\:~/test;DB_CLOSE_ON_EXIT=FALSE

# Enable if you want other applications to connect
#webAllowOthers=true
#webPort=8082
#webSSL=false

刚刚生成了一个全新的 Spring 引导项目 start.spring.io 以及一些依赖项 h2, JPA, web, devtools, actuator。添加一个简单的实体和Spring数据存储库后,数据库确实默认在内存中创建。

将以下内容添加到我的 application.properties 肯定会在正确的位置创建数据库文件:

spring.datasource.url=jdbc:h2:file:~/test;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.username=test
spring.datasource.password=test
spring.datasource.driverClassName=org.h2.Driver

启用 devtools 后,我什至可以使用 H2 控制台连接到它 http://localhost:8080/h2-console/

下一个合乎逻辑的步骤是访问 http://localhost:8080/autoconfig 端点并检查自动配置状态。

就我而言,以下是 positiveMatches:

DataSourceAutoConfiguration.NonEmbeddedConfiguration: [
{
  condition: "DataSourceAutoConfiguration.NonEmbeddedDataSourceCondition",
  message: "supported DataSource class found"
},
{
  condition: "OnBeanCondition",
  message: "@ConditionalOnMissingBean (types: javax.sql.DataSource,javax.sql.XADataSource; SearchStrategy: all) found no beans"
}
],

以及 negativeMatches 中的以下内容:

DataSourceAutoConfiguration.EmbeddedConfiguration: [
{
  condition: "DataSourceAutoConfiguration.EmbeddedDataSourceCondition",
  message: "existing non-embedded database detected"
}
],

您可以尝试以下操作并查看自动配置报告吗?

参考http://www.h2database.com/html/cheatSheet.html

我想这可能是 jdbc.url 的问题,改成这样:

# from:
spring.datasource.url=jdbc:h2:file:~/test;DB_CLOSE_ON_EXIT=FALSE

# to:
spring.datasource.url=jdbc:h2:~/test;DB_CLOSE_ON_EXIT=FALSE

在application.properties上使用以下设置,即使在关闭并重新启动SpringBoot后,甚至在重新启动计算机后,我都设法保持数据持久化。

spring.datasource.name=japodb
spring.datasource.initialize=false
spring.datasource.driverClassName=org.h2.Driver

spring.datasource.url=jdbc:h2:file:~/japodb;DB_CLOSE_ON_EXIT=FALSE;IFEXISTS=TRUE;DB_CLOSE_DELAY=-1;

VM 退出时不要关闭数据库,是的,但如果数据库已经存在,也不要创建新数据库。

jdbc:h2:<url>;IFEXISTS=TRUE

spring.jpa.hibernate.ddl-auto = update

我添加这个答案是为了避免混淆和进一步研究。

实际上我遇到了同样的问题,none 的答案完全适合我,而不是混合使用某些答案。

这是在 spring 引导中保留 H2 数据库所需的最小配置。

application.properties

# H2
spring.h2.console.enabled=true
spring.h2.console.path=/h2
# Datasource
spring.datasource.url=jdbc:h2:file:~/spring-boot-h2-db
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.driver-class-name=org.h2.Driver
spring.jpa.hibernate.ddl-auto=update

这里 spring.jpa.hibernate.ddl-auto=update 可以解决问题。没有其他要求。

无需在pom.xml

中添加spring-boot-starter-jdbc

无需在jdbc中添加任何参数url.

这是适合我的配置

#File based h2 DB
spring.datasource.url=jdbc:h2:file:C:/temp/test_db;DB_CLOSE_ON_EXIT=FALSE;AUTO_RECONNECT=TRUE;DB_CLOSE_DELAY=-1
#In memory
#spring.datasource.url=jdbc:h2:mem:testdb:security_permission;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.driverClassName=org.h2.Driver
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
spring.jpa.hibernate.ddl-auto=update
spring.datasource.username=user
spring.datasource.password=admin
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
#Use datasource.initialization-mode if you are configured to use file based h2 and data.sql
spring.datasource.initialization-mode=always
spring.jpa.defer-datasource-initialization=true

当我使用 data.sql 进行数据初始化时,我必须使用以下选项才能使其工作

spring.datasource.initialization-mode=always

数据初始化后,可以设置为never

spring.datasource.initialization-mode=never