0

我正在编写一个通过 JDBC 使用 SQLite 进行持久性的 Java 应用程序。

应用程序启动时我需要做的是:

  1. 如果数据库不存在,请使用正确的架构创建它
  2. 如果数据库存在,请检查数据库是否具有正确的架构

为了创建数据库,我想将在外部文件中创建结构(例如 CREATE TABLE ...)所需的 SQL 命令外部化,在运行时加载并执行它。我想过使用BufferedReaderwith.readLine()然后将每个 SQL 命令提供给Statement.executeUpdate(). 有没有更聪明的方法来做到这一点?

关于数据库模式的启动检查,虽然我认为这应该被认为是“好的设计”,但我不知道在实践中它是否可能是矫枉过正或无用。我想出的一种解决方案,但具有“依赖于供应商”的缺点是:

  1. 使用所有结构名称的已知前缀创建数据库(例如nwe_
  2. 查询sqlite_masterWHERE name LIKE 'nwe_%'
  3. SQL列的内容与我用于创建数据库的 SQL 命令文件进行比较

同样,有没有更聪明的方法来做到这一点?(也许不是“依赖于供应商”,但当时这对我来说不是什么大问题)

谢谢。

4

2 回答 2

4

我不是专业程序员,这是我的第一个 java 应用程序,但我也决定进行数据库验证。幸运的是,sqlite 数据库有一个系统表,其中包含数据库中每个表的 sql 语句。所以有一种快速而肮脏的方法来检查数据库结构:

public class Model {
    private Map<String, String> tableSql;

    Model(){
        // declare right database's tables syntax 
        tableSql = new HashMap<String, String>();
        tableSql.put("settings",    "CREATE TABLE [settings] ( [id]     INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, [item] ... )");
        tableSql.put("scheta",      "CREATE TABLE [scheta] ( [id] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, [sname] ...)");
        tableSql.put("nomera",      "CREATE TABLE [nomera] ( [id] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, [nvalue] ...)");
        tableSql.put("corr",        "CREATE TABLE [corr] (  [id] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, [cname] ...)");
        tableSql.put("category",    "CREATE TABLE [category] ( [id] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, [cname] ...)");
        tableSql.put("price",       "CREATE TABLE [price] ( [id] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, [cdate] ...)");
    }

    public void Connect( String path){
        File DBfile = new File (path);
        boolean DBexists = DBfile.exists();
        Statement stmt = null;
        ResultSet rs;

        try {
            Class.forName("org.sqlite.JDBC");
            c = DriverManager.getConnection("jdbc:sqlite:" + path);
            c.setAutoCommit(true);

            stmt = c.createStatement();
            if( DBexists ){
                // check database structure
                for (String tableName : tableSql.keySet()) {
                    rs = stmt.executeQuery( "SELECT sql FROM sqlite_master WHERE type = 'table' AND name = '" + tableName + "'");
                    if(rs.isBeforeFirst()){
                        rs.next();
                        // table and field names may be inside square brackets or inside quotes...
                        String table_schema_there = rs.getString(1).replaceAll("\\s+"," ").replaceAll("[\\[\\]'`]", "\"");
                        String table_schema_here = tableSql.get(tableName).replaceAll("\\s+"," ").replaceAll("[\\[\\]'`]", "\"");;
                        if( ! table_schema_there.equals(table_schema_here) ){
                            notifyListeners( new ModelResponse( false, "Structure error. Wrong structure of table "  + tableName));
                            System.exit(0);
                        }
                    }
                    else{
                        notifyListeners( new ModelResponse( false, "Structure error. The table is missing: "  + tableName ));
                        System.exit(0);
                    }
                }
            }
            else{
                // empty DB file created during connection so we need to create schema
                for (String tableName : tableSql.keySet()) {
                    stmt.executeUpdate(tableSql.get(tableName));
                }
            }
        } 
        catch ( Exception e ) {
            notifyListeners( new ModelResponse( false, e.getMessage()));
            System.exit(0);
        }
    }
}
于 2014-04-22T18:21:17.203 回答
1

您可以通过查看元数据表来编写自己的数据库验证。这并非不可能,但需要维护大量代码。您还可以编写大量 DDL 语句来构建数据库结构,这同样不是不可能,但需要维护大量代码。

如果您遵循这样的路径,我建议使用更高级别的逻辑

if (!checkDatabase()) {
  try {
    if (wantsToInstall()) {
      installDatabase();
    }
  } catch (Exception e) {
    exit();
  }
}

或特定的安装程序(以减少安装现有项目的机会)。可以进行提供删除数据项的扩展,但是对于在安装/升级过程中遇到意外的预先存在的对象时如何处理存在不同的意见。

现在有一些库可以为您执行此操作;但是当他们添加此功能时,这样的库可能不仅仅需要简单的数据库结构维护。看看 JDO 和其他一些,我知道 DataNucleus 的环境很乐意创建经过调整的数据库结构,以便在 20 多个不同的数据库中正常工作(请记住,它们在做事方式上都有细微的差异)。

于 2012-06-01T15:17:28.947 回答