Java:数据库检查和初始化

时间:2012-06-01 14:55:50

标签: java sql sqlite db-schema

我正在编写一个Java应用程序,它通过JDBC使用SQLite来实现持久性。

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

  1. 如果数据库不存在,请使用正确的架构
  2. 创建它
  3. 如果数据库存在,请检查数据库是否具有正确的架构
  4. 为了创建数据库我想到在外部文件中外化创建结构所需的SQL命令(例如CREATE TABLE ...),在运行时加载它并执行它。 我想过将BufferedReader.readLine()一起使用,然后将每个SQL命令提供给Statement.executeUpdate()。有更聪明的方法吗?

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

    1. 使用所有结构名称的已知前缀(例如nwe_
    2. 创建数据库
    3. 使用sqlite_master
    4. 查询WHERE name LIKE 'nwe_%'表格
    5. SQL列的内容与我用于创建数据库的SQL命令文件进行比较
    6. 同样,有更聪明的方法吗? (也许不是“供应商依赖”,但这对我来说并不是一个问题)

      感谢。

2 个答案:

答案 0 :(得分:3)

我不是专业程序员,这是我的第一个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);
        }
    }
}

答案 1 :(得分:1)

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

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

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

或特定安装程序(以减少安装现有项目的机会)。可以完成提供删除数据项的扩展,但是如果在安装/升级期间遇到意外的预先存在的对象,该怎么办会有不同的意见。

现在有一些图书馆会为你做这件事;但是当他们添加此功能时,这样的库可能比简单的数据库结构维护更多地处理 。看看JDO和其他一些人,我知道DataNucleus的环境很乐意创建数据库结构,调整后可以在20多个不同的数据库中运行良好(记住它们在处理事务方面都有细微差别)。