内存数据库H2中的Spring Boot在初始化时不会从文件中加载数据
Posted
技术标签:
【中文标题】内存数据库H2中的Spring Boot在初始化时不会从文件中加载数据【英文标题】:Spring Boot in memory database H2 doesn't load data from file on initialization 【发布时间】:2017-06-10 00:17:55 【问题描述】:我在应用程序初始化时将数据加载到内存数据库时遇到问题。我创建了包含表结构和初始数据的 schema.sql 和 data.sql 文件。
schema.sql:
CREATE TABLE users (
id INT PRIMARY KEY,
username VARCHAR(64) NOT NULL,
password VARCHAR(64)
);
和data.sql:
INSERT INTO users (id, username, password) VALUES
(1, 'usr1', 'bigSecret'),
(2, 'usr2', 'topSecret');
我正在使用JpaRepository
处理数据层:
public interface UserRepository extends JpaRepository<User, Long>
而且我还配置了application.properties
spring.datasource.initialize=true
spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=- 1;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
但是当我打电话时
List<User> users = userRepository.findAll();
用户实体
@Entity
@Table(name = "users")
public class User
@Id
@GeneratedValue
private Long id;
private String username;
private String password;
public User()
public Long getId()
return id;
public void setId(Long id)
this.id = id;
public String getUsername()
return username;
public void setUsername(String username)
this.username = username;
public String getPassword()
return password;
public void setPassword(String password)
this.password = password;
我得到一个空列表,但我应该从我的内存 H2 数据库中获取两个预先填充的用户。内存数据库有什么问题? 谢谢。
【问题讨论】:
你把这些脚本放在哪里了? 我想知道您的网址是否可以使用额外的空间DB_CLOSE_DELAY=- 1;
=> DB_CLOSE_DELAY=-1;
你能显示你的User
实体吗
@Maciej Kowalski 我已将脚本放入 /src/main/resources 中,似乎它们已被应用程序读取。
@alexbt 我删除了空间并且结果相同 - 没有从文件中提取数据
【参考方案1】:
您始终可以尝试根据 h2 规范运行这些脚本,您应该在连接 url 中添加一个 INIT 脚本(作为选项之一):
jdbc:h2:mem:test;INIT=RUNSCRIPT FROM '~/schema.sql'\;RUNSCRIPT FROM '~/data.sql'"
此功能通过 INIT 属性启用。注意 可以将多个命令传递给 INIT,但分号分隔符 必须转义,如下例所示。
更新
请注意,在您的 application.properties
中有这些选项:
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=true
spring.datasource.initialize=true
在启动过程中可能会导致一些冲突。因此,您应该始终瞄准其中一个,但绝不能同时瞄准两者。 对于简单的情况,仅这些就足以在关机和启动后自动构建表并重新加载
【讨论】:
我已尝试将 sql 脚本(schema.sql 和 data.sql)添加到 application.conf 的spring.datasource.url
属性中的 INIT,但在应用程序启动时出现异常- 告诉该表已经创建(org.h2.jdbc.JdbcSQLException: 表“USERS”已经存在;SQL 语句),我认为这是因为spring.datasource.initialize=true
。所以......似乎 INIT 和 spring.datasource.initialize=true
不会一起工作。 @Maciej Kowalski
application.conf 的正确设置是:spring.datasource.initialize=true
spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
最重要的是,不要忘记禁用 Hibernate 数据库初始化属性spring.jpa.hibernate.ddl-auto=none
,因为默认值create-drop
将删除之前插入的表中的所有数据。你会有空桌子。
是的,那个 spring.jpa.hibernate.ddl-auto 可能已经妨碍了。很高兴它终于对你有用。
spring.jpa.hibernate.ddl-auto=none 导致我 h2 根本不创建任何表....
感谢@tyomka。您设置 spring.jpa.hibernate.ddl-auto=none 的建议是使其正常工作的关键。它节省了我的时间。【参考方案2】:
当我在 application.properties 中添加以下行时,我解决了类似的问题:
spring.jpa.hibernate.ddl-auto=none
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
spring.session.jdbc.initialize-schema=always
spring.sql.init.data-locations=classpath:schema.sql,classpath:data.sql
【讨论】:
以上是关于内存数据库H2中的Spring Boot在初始化时不会从文件中加载数据的主要内容,如果未能解决你的问题,请参考以下文章
在 Spring Boot 应用程序上使用 Flyway 时如何在 H2 中加载初始数据?
Spring Boot 2.x 实践记:H2 Database
Spring Boot 2.x 实践记:H2 Database