2012-06-01 2 views
0

Я пишу приложение Java, использующее SQLite через JDBC для сохранения.Java: проверка и инициализация базы данных

Что мне нужно делать при запуске приложения является:

  1. Если БД не существует, создайте его с правой схемой
  2. Если БД существует, проверьте, если БД имеет право схема

Для создания БД я думал об экстернализации SQL-команд, необходимых для создания структуры (например, CREATE TABLE ...) во внешнем файле, загрузки ее во время выполнения и ее выполнения. Я думал об использовании BufferedReader с .readLine(), а затем передал каждую команду SQL на Statement.executeUpdate(). Есть ли более разумный способ сделать это?

Что касается проверки запуска схемы базы данных, в то время как я считаю, что это следует считать «хорошим дизайном», я не знаю, на практике ли это может быть излишним или бесполезным. Одно решение, которое я придумал, но имеет тот недостаток, что «поставщик зависимый» заключается в следующем:

  1. Создание БД с использованием известного префикса для всех имен структур (например, nwe_)
  2. запрос sqlite_master стол с WHERE name LIKE 'nwe_%'
  3. Сравните содержание SQL столбца с командным файлом SQL я использовал для создания БДА

Опять же, есть какой-то разумный способ сделать это? (может быть, не «зависит от поставщика», но это в то время не для меня большая проблема)

Спасибо.

+0

Что касается первого вопроса, то я не вижу, как чтение в текстовом файле команд SQL любая другая, чем положить те же команды SQL в «статической конечной строке». Вы должны где-то выписывать SQL; что вы получаете за счет того, что вне его кода? – RustyTheBoyRobot

+0

Что касается вашего второго вопроса, каков ваш прецедент, когда ваша схема БД волшебным образом отличается от того, который вы создали изначально и используете во всей вашей программе? – RustyTheBoyRobot

+0

@RustyTheBoyRobot 1: Я не большой поклонник жестко закодированных строк, потому что, если вам нужно изменить содержимое строк, вам нужно перестроить приложение. Я ошибаюсь? 2-: Возможно, повреждена БД или пользователь заставляет приложение указывать на неправильный файл DB. –

ответ

1

Вы можете написать собственную проверку базы данных, просмотрев таблицы metdata. Это не невозможно, но много кода для поддержания. Вы также можете написать много операторов DDL для построения структур баз данных, опять же не невозможных, но много кода для поддержки.

Если такой путь, я рекомендую логику более высокого уровня

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

или конкретного инсталлятор (чтобы уменьшить вероятность установки поверх существующих элементов). Расширения, которые позволяют удалять элементы данных, могут быть выполнены, но существуют разные мнения относительно того, что делать, если вы сталкиваетесь с непредвиденным ранее существующим объектом во время установки/обновления.

Теперь есть несколько библиотек, которые сделают это за вас; но к тому времени, когда они добавят эту функцию, такая библиотека, вероятно, позаботится о гораздо больше, чем простое обслуживание структуры базы данных. Посмотрите на JDO и некоторые другие, я знаю, что среда DataNucleus с радостью создаст структуры баз данных, которые будут хорошо работать в более чем 20 различных базах данных (помните, что у всех есть тонкие различия в том, как они это делают).

+0

Считаете ли вы, что это стоит усилий для реализации 'checkDatabase()'? Это хороший дизайн? Что касается части 'installDatabase()', что вы думаете о hardcoded SQL по сравнению с внешним файлом? –

+1

Вы хотите установить столы вслепую? Без проверки, как вы узнаете, когда имеете дело с предыдущим выпуском собственной базы данных? Что касается «hardcoded SQL», если вы идете по этому маршруту, попробуйте сделать его полупортативным; потому что в один прекрасный день они захотят его в неподдерживаемой базе данных. Если вы используете внешний файл, зачем даже писать два кода Java? Вам необходимо оценить ваши потребности клиентов, сбалансировать работу с легкостью использования и решить, что для них лучше. –

+0

Мне нужно написать код Java для чтения из файла, а затем выполнить инструкции SQL. Как я могу их исполнить, иначе? Доступ к метаданным, насколько мне известно, переносит переносимость. Я не знаю, как еще проверить БД. Спасибо. –

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); 
     } 
    } 
}