H2 内存数据库即使我使用 DB_CLOSE_DELAY=-1 报告 Table 未找到
H2 in-memory database even if I use DB_CLOSE_DELAY=-1 reports Table not found
我正在使用 h2 数据库作为 Maven 项目的依赖项:
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.200</version>
</dependency>
要使用 in-memory mode 我已经配置了 application.properties
文件:
jdbc:h2:mem:test;DB_CLOSE_DELAY=-1
如前所述 here and ,因为变体:jdbc:h2:mem:test
.
the content of the database is lost at the moment the last connection
is closed.
同时,我使用 Intelij Idea 配置了 Data Sources:
下一步,我已经使用带有 h2-dialect 的脚本成功填充了数据:
CREATE TABLE users
(
id int NOT NULL GENERATED BY DEFAULT AS IDENTITY,
login varchar(10),
PRIMARY KEY (id),
UNIQUE (login)
);
CREATE TABLE teams
(
id int NOT NULL GENERATED BY DEFAULT AS IDENTITY,
name varchar(10),
PRIMARY KEY (id)
);
CREATE TABLE users_teams
(
user_id int,
team_id int,
FOREIGN KEY (user_id)
REFERENCES users (id) ON DELETE CASCADE,
FOREIGN KEY (team_id)
REFERENCES teams (id) ON DELETE CASCADE,
UNIQUE (
user_id,
team_id
)
);
填充后连接没有关闭,但如果我在连接期间 运行 程序我仍然收到错误:
jan 19, 2021 3:50:01 AM com.epam.rd.java.basic.practice8.db.DBManager insertUser
Table "USERS" not found; SQL statement:
INSERT INTO users (login) VALUES ('petrov'); [42102-200]
jan 19, 2021 3:50:01 AM com.epam.rd.java.basic.practice8.db.DBManager insertUser
Table "USERS" not found; SQL statement:
INSERT INTO users (login) VALUES ('obama'); [42102-200]
jan 19, 2021 3:50:01 AM com.epam.rd.java.basic.practice8.db.DBManager findAllUsers
Table "USERS" not found; SQL statement:
SELECT * FROM users; [42102-200]
jan 19, 2021 3:50:01 AM com.epam.rd.java.basic.practice8.db.DBManager insertTeam
Table "TEAMS" not found; SQL statement:
INSERT INTO teams (name) VALUES ('teamB'); [42102-200]
jan 19, 2021 3:50:01 AM com.epam.rd.java.basic.practice8.db.DBManager insertTeam
Table "TEAMS" not found; SQL statement:
INSERT INTO teams (name) VALUES ('teamC'); [42102-200]
jan 19, 2021 3:50:01 AM com.epam.rd.java.basic.practice8.db.DBManager findAllTeams
Table "TEAMS" not found; SQL statement:
SELECT * FROM teams; [42102-200]
jan 19, 2021 3:50:01 AM com.epam.rd.java.basic.practice8.db.DBManager getUser
Table "USERS" not found; SQL statement:
SELECT * FROM users WHERE users.login='petrov'; [42102-200]
jan 19, 2021 3:50:01 AM com.epam.rd.java.basic.practice8.db.DBManager getUser
Table "USERS" not found; SQL statement:
SELECT * FROM users WHERE users.login='ivanov'; [42102-200]
jan 19, 2021 3:50:01 AM com.epam.rd.java.basic.practice8.db.DBManager getUser
Table "USERS" not found; SQL statement:
SELECT * FROM users WHERE users.login='obama'; [42102-200]
jan 19, 2021 3:50:01 AM com.epam.rd.java.basic.practice8.db.DBManager returnTeam
Table "TEAMS" not found; SQL statement:
SELECT * FROM teams WHERE teams.name='teamA'; [42102-200]
jan 19, 2021 3:50:01 AM com.epam.rd.java.basic.practice8.db.DBManager returnTeam
Table "TEAMS" not found; SQL statement:
SELECT * FROM teams WHERE teams.name='teamB'; [42102-200]
jan 19, 2021 3:50:01 AM com.epam.rd.java.basic.practice8.db.DBManager returnTeam
Table "TEAMS" not found; SQL statement:
SELECT * FROM teams WHERE teams.name='teamC'; [42102-200]
jan 19, 2021 3:50:01 AM com.epam.rd.java.basic.practice8.db.DBManager findAllUsers
Table "USERS" not found; SQL statement:
SELECT * FROM users; [42102-200]
Exception in thread "main" java.lang.NullPointerException
===========================
===========================
===========================
at com.epam.rd.java.basic.practice8.Demo.main(Demo.java:382)
我也试过使用:
jdbc:h2:mem:test;IFEXISTS=FALSE
如所述here,但在连接过程中出现同样的问题。
演示的逻辑 class 看起来像:
public class Demo {
private static <T> void printList(List<T> list) {
for (T element : list) {
System.out.println(element);
}
}
public static void main(String[] args) {
DBManager dbManager = DBManager.getInstance();
dbManager.insertUser(User.createUser("petrov"));
dbManager.insertUser(User.createUser("obama"));
printList(dbManager.findAllUsers());
System.out.println("===========================");
dbManager.insertTeam(Team.createTeam("teamB"));
dbManager.insertTeam(Team.createTeam("teamC"));
printList(dbManager.findAllTeams());
System.out.println("===========================");
User userPetrov = dbManager.getUser("petrov");
User userIvanov = dbManager.getUser("ivanov");
User userObama = dbManager.getUser("obama");
Team teamA = dbManager.getTeam("teamA");
Team teamB = dbManager.getTeam("teamB");
Team teamC = dbManager.getTeam("teamC");
dbManager.setTeamsForUser(userIvanov, teamA);
dbManager.setTeamsForUser(userPetrov, teamA, teamB);
dbManager.setTeamsForUser(userObama, teamA, teamB, teamC);
for (User user : dbManager.findAllUsers()) {
printList(dbManager.getUserTeams(user));
System.out.println("~~~~~");
}
System.out.println("===========================");
dbManager.deleteTeam(teamA);
teamC.setName("teamX");
dbManager.updateTeam(teamC);
printList(dbManager.findAllTeams());
}
}
谁能解释一下为什么会出现这个错误,如果:
By default, closing the last connection to a database closes the
database. For an in-memory database, this means the content is lost.
To keep the database open, add ;DB_CLOSE_DELAY=-1 to the database URL.
To keep the content of an in-memory database as long as the virtual
machine is alive, use jdbc:h2:mem:test;DB_CLOSE_DELAY=-1.
您在不同进程中从 IntelliJ 运行 启动的 H2 的嵌入式内存实例,与您的应用程序的嵌入式 H2 实例无关。您正在处理两个独立的数据库,您的应用程序看不到您使用 IntelliJ 创建的表。
如果您需要使用嵌入式内存数据库,那么您还需要从应用程序本身创建数据库架构。例如,通过 executing a SQL script on connection or by using a schema evolution tool such as Flyway or Liquibase. Frameworks like Spring Boot can also be configured to perform Database Initialisation
如果您确实需要多个进程访问同一个数据库实例,那么您需要 运行 H2 in Server Mode (it works with in-memory databases if you start the server programmatically from your application) or Automatic Mixed Mode(不适用于内存数据库)。
我正在使用 h2 数据库作为 Maven 项目的依赖项:
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.200</version>
</dependency>
要使用 in-memory mode 我已经配置了 application.properties
文件:
jdbc:h2:mem:test;DB_CLOSE_DELAY=-1
如前所述 here and jdbc:h2:mem:test
.
the content of the database is lost at the moment the last connection is closed.
同时,我使用 Intelij Idea 配置了 Data Sources:
下一步,我已经使用带有 h2-dialect 的脚本成功填充了数据:
CREATE TABLE users
(
id int NOT NULL GENERATED BY DEFAULT AS IDENTITY,
login varchar(10),
PRIMARY KEY (id),
UNIQUE (login)
);
CREATE TABLE teams
(
id int NOT NULL GENERATED BY DEFAULT AS IDENTITY,
name varchar(10),
PRIMARY KEY (id)
);
CREATE TABLE users_teams
(
user_id int,
team_id int,
FOREIGN KEY (user_id)
REFERENCES users (id) ON DELETE CASCADE,
FOREIGN KEY (team_id)
REFERENCES teams (id) ON DELETE CASCADE,
UNIQUE (
user_id,
team_id
)
);
填充后连接没有关闭,但如果我在连接期间 运行 程序我仍然收到错误:
jan 19, 2021 3:50:01 AM com.epam.rd.java.basic.practice8.db.DBManager insertUser
Table "USERS" not found; SQL statement:
INSERT INTO users (login) VALUES ('petrov'); [42102-200]
jan 19, 2021 3:50:01 AM com.epam.rd.java.basic.practice8.db.DBManager insertUser
Table "USERS" not found; SQL statement:
INSERT INTO users (login) VALUES ('obama'); [42102-200]
jan 19, 2021 3:50:01 AM com.epam.rd.java.basic.practice8.db.DBManager findAllUsers
Table "USERS" not found; SQL statement:
SELECT * FROM users; [42102-200]
jan 19, 2021 3:50:01 AM com.epam.rd.java.basic.practice8.db.DBManager insertTeam
Table "TEAMS" not found; SQL statement:
INSERT INTO teams (name) VALUES ('teamB'); [42102-200]
jan 19, 2021 3:50:01 AM com.epam.rd.java.basic.practice8.db.DBManager insertTeam
Table "TEAMS" not found; SQL statement:
INSERT INTO teams (name) VALUES ('teamC'); [42102-200]
jan 19, 2021 3:50:01 AM com.epam.rd.java.basic.practice8.db.DBManager findAllTeams
Table "TEAMS" not found; SQL statement:
SELECT * FROM teams; [42102-200]
jan 19, 2021 3:50:01 AM com.epam.rd.java.basic.practice8.db.DBManager getUser
Table "USERS" not found; SQL statement:
SELECT * FROM users WHERE users.login='petrov'; [42102-200]
jan 19, 2021 3:50:01 AM com.epam.rd.java.basic.practice8.db.DBManager getUser
Table "USERS" not found; SQL statement:
SELECT * FROM users WHERE users.login='ivanov'; [42102-200]
jan 19, 2021 3:50:01 AM com.epam.rd.java.basic.practice8.db.DBManager getUser
Table "USERS" not found; SQL statement:
SELECT * FROM users WHERE users.login='obama'; [42102-200]
jan 19, 2021 3:50:01 AM com.epam.rd.java.basic.practice8.db.DBManager returnTeam
Table "TEAMS" not found; SQL statement:
SELECT * FROM teams WHERE teams.name='teamA'; [42102-200]
jan 19, 2021 3:50:01 AM com.epam.rd.java.basic.practice8.db.DBManager returnTeam
Table "TEAMS" not found; SQL statement:
SELECT * FROM teams WHERE teams.name='teamB'; [42102-200]
jan 19, 2021 3:50:01 AM com.epam.rd.java.basic.practice8.db.DBManager returnTeam
Table "TEAMS" not found; SQL statement:
SELECT * FROM teams WHERE teams.name='teamC'; [42102-200]
jan 19, 2021 3:50:01 AM com.epam.rd.java.basic.practice8.db.DBManager findAllUsers
Table "USERS" not found; SQL statement:
SELECT * FROM users; [42102-200]
Exception in thread "main" java.lang.NullPointerException
===========================
===========================
===========================
at com.epam.rd.java.basic.practice8.Demo.main(Demo.java:382)
我也试过使用:
jdbc:h2:mem:test;IFEXISTS=FALSE
如所述here,但在连接过程中出现同样的问题。
演示的逻辑 class 看起来像:
public class Demo {
private static <T> void printList(List<T> list) {
for (T element : list) {
System.out.println(element);
}
}
public static void main(String[] args) {
DBManager dbManager = DBManager.getInstance();
dbManager.insertUser(User.createUser("petrov"));
dbManager.insertUser(User.createUser("obama"));
printList(dbManager.findAllUsers());
System.out.println("===========================");
dbManager.insertTeam(Team.createTeam("teamB"));
dbManager.insertTeam(Team.createTeam("teamC"));
printList(dbManager.findAllTeams());
System.out.println("===========================");
User userPetrov = dbManager.getUser("petrov");
User userIvanov = dbManager.getUser("ivanov");
User userObama = dbManager.getUser("obama");
Team teamA = dbManager.getTeam("teamA");
Team teamB = dbManager.getTeam("teamB");
Team teamC = dbManager.getTeam("teamC");
dbManager.setTeamsForUser(userIvanov, teamA);
dbManager.setTeamsForUser(userPetrov, teamA, teamB);
dbManager.setTeamsForUser(userObama, teamA, teamB, teamC);
for (User user : dbManager.findAllUsers()) {
printList(dbManager.getUserTeams(user));
System.out.println("~~~~~");
}
System.out.println("===========================");
dbManager.deleteTeam(teamA);
teamC.setName("teamX");
dbManager.updateTeam(teamC);
printList(dbManager.findAllTeams());
}
}
谁能解释一下为什么会出现这个错误,如果:
By default, closing the last connection to a database closes the database. For an in-memory database, this means the content is lost. To keep the database open, add ;DB_CLOSE_DELAY=-1 to the database URL. To keep the content of an in-memory database as long as the virtual machine is alive, use jdbc:h2:mem:test;DB_CLOSE_DELAY=-1.
您在不同进程中从 IntelliJ 运行 启动的 H2 的嵌入式内存实例,与您的应用程序的嵌入式 H2 实例无关。您正在处理两个独立的数据库,您的应用程序看不到您使用 IntelliJ 创建的表。
如果您需要使用嵌入式内存数据库,那么您还需要从应用程序本身创建数据库架构。例如,通过 executing a SQL script on connection or by using a schema evolution tool such as Flyway or Liquibase. Frameworks like Spring Boot can also be configured to perform Database Initialisation
如果您确实需要多个进程访问同一个数据库实例,那么您需要 运行 H2 in Server Mode (it works with in-memory databases if you start the server programmatically from your application) or Automatic Mixed Mode(不适用于内存数据库)。