我有一个数据库架构,可以创建多个表并用数据填充它们。我想在应用启动期间检查db是否包含相应的表。我可以检查db文件是否存在,但如果不存在,H2会创建db。因此,我认为唯一的方法是检查表的存在。
以下是我如何初始化DB的代码:
Class.forName("org.h2.Driver");
Connection conn = DriverManager.getConnection("jdbc:h2:database/svc", "sa", "");
Statement st = conn.createStatement();
st.execute("CREATE TABLE IF NOT EXISTS table1 (id INT PRIMARY KEY AUTO_INCREMENT NOT NULL, name VARCHAR(100), record INT, record_date DATE, UNIQUE(name))");
st.execute("CREATE TABLE IF NOT EXISTS table2 (id INT PRIMARY KEY AUTO_INCREMENT NOT NULL, name VARCHAR(100), record INT, record_date DATE, UNIQUE(name))");
st.execute("CREATE TABLE IF NOT EXISTS daily_record_stat (id INT PRIMARY KEY AUTO_INCREMENT NOT NULL, date DATE, table1_id INT, table1_record INT, table2_id INT," +
" table2_record INT, total_record INT);");
st.execute("ALTER TABLE daily_record_stat ADD FOREIGN KEY (table1_id) REFERENCES table1(id);");
st.execute("ALTER TABLE daily_record_stat ADD FOREIGN KEY (table2_id) REFERENCES table2(id);");
st.execute("INSERT INTO table1 VALUES(1, 'non_existed_stub', 0, NULL)");
st.execute("INSERT INTO table2 VALUES(1, 'non_existed_stub', 0, NULL)");
conn.close();
如您所见,我使用IF NOT EXISTS
语句在创建之前检查表是否存在。但后来我使用ALTER
和INSERT
来解决问题 - 这些命令不允许使用IF。
我尝试执行以下操作:
Connection conn = DriverManager.getConnection("jdbc:h2:database/svc", "sa", "");
ResultSet meta = conn.getMetaData().getTables(null, null, "table1", null);
if(meta.next()) {
//do something
}
但meta.next()
为false
。
那么如何检查表模式是否已初始化?或者这应该以其他方式完成?
答案 0 :(得分:3)
通过以编程方式检查,确定这是不是您的意思,购买后可以尝试使用DatabaseMetaData.getTables()
。此调用将返回ResultSet
,您必须以编程方式检查。您可以在相应的here部分中查看此ResultSet
中返回的字段。元数据本身可以通过conn.getMetaData()
获得。
以下代码应返回名称以“TABLE”开头的所有表:
ResultSet meta = conn.getMetaData().getTables(null, null, "TABLE%", new String[]{"TABLE"});
while (meta.next()) {
System.out.println(meta.getString(3));
}
请注意,您必须以大写形式指定表名模式。最好传递你需要的表类型,尽管它是可选的。
答案 1 :(得分:1)
这是我以前(重新)创建H2数据库的检查:
// IMPORTANT A sorted list of table names.
private static final String[] REQUIRED_TABLES = { "USER", ... };
public static final String CREATE_USER = "create table USER (...)";
private boolean schemaExists() throws SQLException {
final List<String> requiredTables = Arrays.asList(REQUIRED_TABLES);
final List<String> tableNames = new ArrayList<String>();
final Connection conn = dataSource.getConnection();
try {
final Statement st = conn.createStatement();
final ResultSet rs = st.executeQuery("show tables");
while (rs.next()) {
tableNames.add(rs.getString("TABLE_NAME"));
}
rs.close();
st.close();
}
finally {
if (conn != null) { conn.close(); }
}
Collections.sort(tableNames);
return tableNames.equals(requiredTables);
}
private void initializeDatabase() throws SQLException {
final Connection conn = dataSource.getConnection();
try {
if (schemaExists()) {
return;
}
final Statement st = conn.createStatement();
st.executeUpdate(CREATE_USER);
conn.commit();
}
finally {
if (conn != null) { conn.close(); }
}
}
你只需致电:
initializeDatabase();
请注意,必须对必需表的列表进行排序,因为我使用List.equals()
来比较两个列表。最好也可以通过编程方式对所需的表列表进行排序。
这不是万无一失的(不检查是否存在任何表格以及是否应该更改)但它对我有用。
请查看SHOW命令以了解其他用途。