H2 DB:如何检查表模式是否以编程方式初始化?

时间:2013-12-25 13:58:56

标签: java h2

我有一个数据库架构,可以创建多个表并用数据填充它们。我想在应用启动期间检查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语句在创建之前检查表是否存在。但后来我使用ALTERINSERT来解决问题 - 这些命令不允许使用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

那么如何检查表模式是否已初始化?或者这应该以其他方式完成?

2 个答案:

答案 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命令以了解其他用途。