我正在编写一个Java应用程序,它通过JDBC使用SQLite来实现持久性。
应用程序启动时我需要做的是:
为了创建数据库我想到在外部文件中外化创建结构所需的SQL命令(例如CREATE TABLE ...),在运行时加载它并执行它。
我想过将BufferedReader
与.readLine()
一起使用,然后将每个SQL命令提供给Statement.executeUpdate()
。有更聪明的方法吗?
关于数据库架构的启动检查,虽然我认为这应该被认为是“好的设计”,但我不知道在实践中它是否有点过分或无用。 我提出的一个解决方案但是具有“依赖于供应商”的缺点是:
nwe_
)sqlite_master
WHERE name LIKE 'nwe_%'
表格
SQL
列的内容与我用于创建数据库的SQL命令文件进行比较同样,有更聪明的方法吗? (也许不是“供应商依赖”,但这对我来说并不是一个问题)
感谢。
答案 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多个不同的数据库中运行良好(记住它们在处理事务方面都有细微差别)。