我正在编写一个 Java 应用程序,它通过 JDBC 使用 SQLite 来实现持久性。
应用程序启动时我需要做的是:
- 如果数据库不存在,请使用正确的架构创建它
- 如果数据库存在,请检查数据库是否具有正确的架构
为了创建数据库,我想到将创建结构(例如 CREATE TABLE ...)所需的 SQL 命令外部化在外部文件中,在运行时加载并执行它。 我考虑将 BufferedReader 与 .readLine() 结合使用,然后将每个 SQL 命令提供给 Statement.executeUpdate()。有没有更聪明的方法来做到这一点?
关于数据库模式的启动检查,虽然我认为这应该被认为是“好的设计”,但我不知道在实践中它是否会矫枉过正或无用。 我提出的一种解决方案,但其缺点是“依赖于供应商”:
- 使用所有结构名称的已知前缀(例如
nwe_
)创建数据库 - 使用
WHERE name LIKE 'nwe_%'
查询sqlite_master
表 - 将
SQL
列的内容与我用于创建数据库的 SQL 命令文件进行比较
再说一遍,有没有更聪明的方法来做到这一点? (也许不是“依赖于供应商”,但这对我来说并不是什么大问题)
谢谢。
最佳答案
我不是专业程序员,这是我的第一个 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);
}
}
}
关于Java:数据库检查和初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10852626/