Java 内存数据库中的 h2 JdbcSQLSyntaxErrorException: Table "table_name" 未找到
Java h2 in memory database JdbcSQLSyntaxErrorException: Table "table_name" not found
我正在尝试使用内存数据库测试 JDBC 客户端,因此我可以使用单元测试来测试各种情况。
这是我目前的情况:
模型class(也包含构造函数)
@Entity
@Table(name = "table_name")
public class MyModel {
我有一个客户端 class,我想用它与 postgres 交互,使用 java.sql DriverManager 和 PreparedStatements。
public class MyModelClient {
private final Connection con;
public MyModelClient(String url, String user, String password) {
try {
con = DriverManager.getConnection(url, user, password);
} catch (SQLException e) {
throw new RuntimeException("uh oh", e);
}
}
public Connection getCon() {
return con;
}
private static String ROWS = "\"uuid\", ...";
private String insertMyModelQuery() {
return "INSERT INTO table_name (" + MyModelClient.ROWS + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" +
"ON CONFLICT(\"uuid\") DO UPDATE SET url=EXCLUDED.url RETURNING uuid;";
}
public void insertMyModel(MyModel article) {
try (PreparedStatement preparedStatement = con.prepareStatement(this.insertMyModelQuery())) {
preparedStatement.setObject(1, article.uuid);
...
preparedStatement.executeUpdate();
} catch (SQLException e) {
throw new InsertMyModelException("failed to insert MyModel: " + e.toString(), e);
}
}
}
我有我想要的单元测试 运行。我希望它通过客户端连接到内存数据库,在测试设置时创建数据库,然后测试我的插入方法。
public class MyModelClientTest {
static MyModelClient client;
@BeforeAll
public static void setUp() {
client = new ArticleClient("jdbc:h2:mem:testdb;DATABASE_TO_UPPER=false;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE", "postgres", "mysecretpassword");
String sql = "-- template"+
"CREATE TABLE my_model_template ("+
" uuid UUID NOT NULL,"+
... +
");";
String sql2 = "-- Create table"+
"CREATE TABLE table_name"+
" (LIKE my_model_template)"+
" PARTITION BY RANGE (created_datetime);";
try {
Statement s=client.getCon().createStatement();
s.execute(sql);
s.execute(sql2);
} catch (SQLException e) {
e.printStackTrace();
}
}
@Test
public void shouldInsertMyModel() {
System.out.println("TEST---------------------");
MyModel m = TestMyModelBuilder.build();
client.insertMyModel(m);
}
}
我期望发生的事情
设置方法创建 table。我的测试插入到 table
实际发生了什么
记录显示设置为 运行。测试是 运行,但插入失败,因为 table 显然不存在。
failed to insert MyModel: org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "table_name" not found;
我的 application.properties 在测试目录中看起来像:
spring.datasource.url=jdbc:h2:mem:testdb;DATABASE_TO_UPPER=false;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=postgres
spring.datasource.password=mysecretpassword
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.defer-datasource-initialization=true
当您在 application.properties 文件中使用了错误的方言,或者您验证了错误的数据库时,就会发生这种情况。例如,当你 运行 你的应用程序针对本地 H2 数据库时,最好的选择是删除方言,因为 Hibernate 可以在没有这个 属性 的情况下识别数据库(如果 Hibernate 的版本足够新识别较新的数据库)。另一种解决方案是删除 validate 属性,但我不建议这样做,因为您在启动时没有进行数据库检查:
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
spring.jpa.hibernate.ddl-auto=update
您对 SQL 的评论中缺少 \n
。现在整个 SQL 语句被解释为注释,因此不会执行任何内容。
String sql = "-- template\n"+
"CREATE TABLE my_model_template ("+
" uuid UUID NOT NULL,"+
... +
");";
类似的东西,或者如果您使用的是较新版本的 Java,您甚至可以使用文本块。
String sql = """-- template
CREATE TABLE my_model_template (
uuid UUID NOT NULL,"+
...
);""";
这适用于 Java 15(启用实验性功能)或 Java 17 或更高版本。
我正在尝试使用内存数据库测试 JDBC 客户端,因此我可以使用单元测试来测试各种情况。
这是我目前的情况:
模型class(也包含构造函数)
@Entity
@Table(name = "table_name")
public class MyModel {
我有一个客户端 class,我想用它与 postgres 交互,使用 java.sql DriverManager 和 PreparedStatements。
public class MyModelClient {
private final Connection con;
public MyModelClient(String url, String user, String password) {
try {
con = DriverManager.getConnection(url, user, password);
} catch (SQLException e) {
throw new RuntimeException("uh oh", e);
}
}
public Connection getCon() {
return con;
}
private static String ROWS = "\"uuid\", ...";
private String insertMyModelQuery() {
return "INSERT INTO table_name (" + MyModelClient.ROWS + ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" +
"ON CONFLICT(\"uuid\") DO UPDATE SET url=EXCLUDED.url RETURNING uuid;";
}
public void insertMyModel(MyModel article) {
try (PreparedStatement preparedStatement = con.prepareStatement(this.insertMyModelQuery())) {
preparedStatement.setObject(1, article.uuid);
...
preparedStatement.executeUpdate();
} catch (SQLException e) {
throw new InsertMyModelException("failed to insert MyModel: " + e.toString(), e);
}
}
}
我有我想要的单元测试 运行。我希望它通过客户端连接到内存数据库,在测试设置时创建数据库,然后测试我的插入方法。
public class MyModelClientTest {
static MyModelClient client;
@BeforeAll
public static void setUp() {
client = new ArticleClient("jdbc:h2:mem:testdb;DATABASE_TO_UPPER=false;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE", "postgres", "mysecretpassword");
String sql = "-- template"+
"CREATE TABLE my_model_template ("+
" uuid UUID NOT NULL,"+
... +
");";
String sql2 = "-- Create table"+
"CREATE TABLE table_name"+
" (LIKE my_model_template)"+
" PARTITION BY RANGE (created_datetime);";
try {
Statement s=client.getCon().createStatement();
s.execute(sql);
s.execute(sql2);
} catch (SQLException e) {
e.printStackTrace();
}
}
@Test
public void shouldInsertMyModel() {
System.out.println("TEST---------------------");
MyModel m = TestMyModelBuilder.build();
client.insertMyModel(m);
}
}
我期望发生的事情
设置方法创建 table。我的测试插入到 table
实际发生了什么
记录显示设置为 运行。测试是 运行,但插入失败,因为 table 显然不存在。
failed to insert MyModel: org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "table_name" not found;
我的 application.properties 在测试目录中看起来像:
spring.datasource.url=jdbc:h2:mem:testdb;DATABASE_TO_UPPER=false;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=postgres
spring.datasource.password=mysecretpassword
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.defer-datasource-initialization=true
当您在 application.properties 文件中使用了错误的方言,或者您验证了错误的数据库时,就会发生这种情况。例如,当你 运行 你的应用程序针对本地 H2 数据库时,最好的选择是删除方言,因为 Hibernate 可以在没有这个 属性 的情况下识别数据库(如果 Hibernate 的版本足够新识别较新的数据库)。另一种解决方案是删除 validate 属性,但我不建议这样做,因为您在启动时没有进行数据库检查:
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
spring.jpa.hibernate.ddl-auto=update
您对 SQL 的评论中缺少 \n
。现在整个 SQL 语句被解释为注释,因此不会执行任何内容。
String sql = "-- template\n"+
"CREATE TABLE my_model_template ("+
" uuid UUID NOT NULL,"+
... +
");";
类似的东西,或者如果您使用的是较新版本的 Java,您甚至可以使用文本块。
String sql = """-- template
CREATE TABLE my_model_template (
uuid UUID NOT NULL,"+
...
);""";
这适用于 Java 15(启用实验性功能)或 Java 17 或更高版本。