如何使用内存数据库让 H2 和 SpringBoot 协同工作?

How do I get H2 and SpringBoot to play nice together using the in memory database?

我正在学习关于使用 JUnit 和 Mockito 进行单元测试的教程视频,并且 运行 遇到了一些问题,其中有些东西播放不佳,我正在尝试找出问题所在。本教程使用 H2 创建内存数据库,这是我遇到问题的地方(数据库没有数据)。我创建了一个新项目,其唯一目的是创建相同的数据库,该数据库在一定程度上起作用,然后因没有数据而失败。经过几天的研究,我希望有人能看到我遗漏的一些明显的东西。我正在使用 IntelliJ Idea 21.1.2 作为我的 IDE、Linux Mint OS。 H2 对我来说是新的。

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>TestH2</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>TestH2</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

application.properties

spring.datasource.url=jdbc:h2:mem:item;DB_CLOSE_ON_EXIT=FALSE;DB_CLOSE_DELAY=-1
spring.h2.console.enabled=true

schema.sql

DROP TABLE IF EXISTS ITEM;

CREATE TABLE ITEM (
    id INT,
    name VARCHAR(255),
    price INT,
    quantity INT
);

data.sql

INSERT INTO ITEM(id, name, price, quantity)
VALUES
       (10001,'Item1',10,20),
       (10002,'Item2',5,10),
       (10003,'Item3',15,2);

有了上面的内容和我的应用程序文件,项目就构建好了,当我打开 h2-console 时,我得到了预期的结果。

不过。 . .

如果我尝试添加这样的 Item.java 文件(请注意,如果我注释掉 @Entity 行,它会如上所示工作)

package com.example.testh2.model;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Transient;

@Entity
public class Item {

    @Id
    private int id;
    private String name;
    private int price;
    private int quantity;

    @Transient
    private int value;

    public Item() {

    }

    public Item(int id, String name, int price, int quantity) {
        this.id = id;
        this.name = name;
        this.price = price;
        this.quantity = quantity;

    }

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

    public int getPrice() {
        return price;
    }
    public void setPrice(int price) {
        this.price = price;
    }

    public int getQuantity() {
        return quantity;
    }
    public void setQuantity(int quantity) {
        this.quantity = quantity;
    }

    public int getValue() { return value; }
    public void setValue(int value) { this.value = value; }


    public String toString() {
        return String.format("Item[%d, %s, %d, %d]", id, name, price, quantity);
    }


}

那就没有数据了

我猜我漏掉了一些简单的东西,我只是还没有 Google 找到正确的问题。我已经尝试了默认值以及当前的 datasource.url,我已经尝试使用一个文件嵌入 H2(我看到 items.mv.db 文件出现在它应该出现的位置但是控制台没有找到它也没有IntelliJ 数据库工具)。任何帮助将不胜感激。

application.properties 文件中,添加此行以关闭冲突的自动架构创建:

spring.jpa.hibernate.ddl-auto=none

您可以在此处阅读更多相关信息: https://docs.spring.io/spring-boot/docs/1.1.0.M1/reference/html/howto-database-initialization.html

要记住的要点:

  1. H2 是一个内存数据库。也就是说,如果您重新启动应用程序,现有数据将会丢失。
  2. 您的依赖项中有 spring 开发工具,当您在应用程序中执行 change/add/modify class/anything 时,它会重新启动应用程序。

根据您的评论:-

However. . .

If I try to add an Item.java file like this (note if I comment out the @Entity line it works as shown above)

看来您是先通过 H2 控制台添加数据,然后 adding/modifiying class , 如果您 add/modify class 在插入数据后:spring 开发工具将重新启动您的应用程序并且您的 h2 数据将会丢失。

建议添加实体 class,然后将数据添加到 h2 数据库,并确保在添加数据后不要更改项目中的任何内容。