H2数据库表未找到错误(Spring Boot)

环境

MacOS Big Sur 11.1
STS 4-4.9.0
Spring Boot 2.4.2
Java 11
H2数据库 1.4.200
Maven 4.0.0

当前的情况

H2Database是一种在JVM环境下运行的数据库。
它非常轻量,在Java测试开发中非常方便。
它有两种类型,一种是内嵌类型,在JVM内部设置数据库,另一种是本地类型,将数据库文件存放在指定路径并进行保存。

这次为了将数据持久化,进行了本地型H2的设置。

文件

入口点

package com.example.h2test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;

import com.example.h2test.domain.Customer;

@SpringBootApplication
public class H2testApplication implements CommandLineRunner {
    @Autowired
    NamedParameterJdbcTemplate jdbcTemplate;

    @Override
    public void run(String...strings) throws Exception {
        String sql = "SELECT id, firstName, lastName from customers where id = :id";
        SqlParameterSource param = new MapSqlParameterSource().addValue("id", 1);
        Customer result = jdbcTemplate.queryForObject(sql, param, (rs, rowNum)
                -> new Customer(rs.getInt("id"), rs.getString("firstName"), rs.getString("lastName")
                ));
        System.out.println("result: " + result);    
    }


    public static void main(String[] args) {
        SpringApplication.run(H2testApplication.class, args);
    }

}

在类路径下,有一个名为schema.sql的文件。

CREATE table IF NOT EXISTS customers (
    id int primary key auto_increment,
    firstName varchar(30),
    lastName varchar(30)
);

在application.properties文件中描述用于将H2数据库持久化的配置。

spring.datasource.driverClassName=org.h2.Driver
spring.datasource.url=jdbc:h2:file:./target/db/testdb
spring.datasource.username=sa
spring.datasource.password=

然而,在执行之后

java.lang.IllegalStateException: Failed to execute CommandLineRunner

Caused by: org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [SELECT id, firstName, lastName from customers where id = ?]; nested exception is org.h2.jdbc.JdbcSQLSyntaxErrorException: テーブル "CUSTOMERS" が見つかりません
Table "CUSTOMERS" not found;

发生了上述错误。
这是用来引用datasource.url路径中所写的数据库文件的配置。
如果不存在,那么会在那里创建一个数据库文件。

错误的原因和解决方案

造成無法找到表的原因是因為根本就沒有創建表。
如果Spring boot的類路徑下有一個名為schema.sql的文件,它會自動讀取並創建表,但目前看來似乎沒有被讀取。

原因是因为SQL文件的初始化设置没有进行。

将以下代码追加到application.properties文件中。

spring.datasource.initialization-mode=always
spring.datasource.schema=classpath:schema.sql
初始化模式

指定如何初始化H2读取的schema.sql文件。可以选择值为「always」、「embedded」或「never」。初始值为embedded,这表示仅在嵌入式数据库(H2数据库)上运行时执行。由于本次是本地数据库而不是嵌入式数据库,如果初始设置不为「always」,则schema.sql将不会被执行。

模式

指定要读取哪个schema文件。
如果未设置,将读取类路径下的schema.sql文件。
(本次可以省略)

最后的application.properties文件的内容将变成这样。

spring.datasource.driverClassName=org.h2.Driver
spring.datasource.url=jdbc:h2:file:./target/db/testdb
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.initialization-mode=always
spring.datasource.schema=classpath:schema.sql

整理

我在参考《はじめてのSpring Boot》的同时处理了h2数据库。
因为在指定文件时没有描述初始化操作,所以让我想是否h2在数年前读取时不需要进行初始化设置呢?

如果有任何错误或建议,请不吝赐教。谢谢。

文献参考

首次使用Spring Boot
Spring Boot的数据库初始化方法
Spring Boot 2.0按类别列出的重要属性列表

广告
将在 10 秒后关闭
bannerAds