最终编辑,问题“已解决”
所以我最终按照接受的答案做了什么,我删除了将数据库版本作为参数的构造函数,但这仍然导致异常。因此,正如还建议的那样,我添加try{} catch{}
了一个块来捕获问题,让我告诉你,它仍然显示抛出异常,只是这次它不会使应用程序崩溃。幸运的是,尽管创建数据库似乎有问题,但它允许我将数据库内容加载到应用程序中,所以我现在对那个日志消息很好:)
这是 onCreate:
@Override
public void onCreate(SQLiteDatabase db) {
Constants.logMessage("Creating database from scratch?");
//Create both of the tables as part of the databases
try {
db.execSQL(CREATE_TABLE_COUNTRIES);
db.execSQL(CREATE_TABLE_REGIONS);
db.execSQL(CREATE_TABLE_CITIES);
}
catch (Exception e) {
//This happens on every launch that isn't the first one.
Log.w("SpotTheStation", "Error while creating db: " + e.toString());
}
}
我在我的 android 应用程序上使用 SQLite,似乎遇到了一个非常奇怪的问题。似乎每次我调用getWriteableDatabase()
系统都会尝试重新创建整个数据库,即它调用onCreate()
,这会导致 SQLiteException。
这是完整的错误消息:
03-21 14:36:44.082: V/SpotTheStation(20034): android.database.sqlite.SQLiteException:,
while compiling: create table countries(_id integer primary key autoincrement,
country text);
每次我尝试访问 DBdata 时都会发生这种情况,我有一个单独的静态类来处理整个应用程序生命周期中的 DB 访问,我通过以下方式将上下文传递给它:
public static Cursor getCountries (final Context context) {
if (mDatabase == null || !mDatabase.isOpen()) {
Constants.logMessage("DB was null, opening");
open(context);
}
return mDatabase.query(CountryDbHelper.TABLE_COUNTRIES, CountryDbHelper.PROJECTION_COUNTRIES, null, null, null, null, CountryDbHelper.DEFAULT_SORT_ORDER);
}
每次我调用这个方法时,日志都会指出实际上是在打开数据库,这很好。这是我打开数据库的方法:
private static void open (Context context) {
if (mDatabase != null && mDatabase.isOpen()) {
return;
}
try {
mHelper = new CountryDbHelper(context);
mDatabase = mHelper.getWritableDatabase();
} catch (Exception e) {
Constants.logMessage(e.toString());
}
}
这就是导致异常的语句,因为 getWriteableDatabase 应该有一个缓存的数据库,或者应该调用onOpen()
而不是onCreate()
.
这是似乎在每个 db 访问调用上执行的 create 语句:
private static final String DATABASE_CREATE = "create table " + TABLE_COUNTRIES
+ "(_id integer primary key autoincrement, "
+ "country text);"
;
这onCreate()
是相当简单的:
@Override
public void onCreate(SQLiteDatabase db) {
Constants.logMessage("Creating database from scratch?");
db.execSQL(DATABASE_CREATE);
}
我添加了日志消息来跟踪问题,这是进展情况:
03-21 14:36:44.004: V/SpotTheStation(20034): DB was null, opening
03-21 14:36:44.035: V/SpotTheStation(20034): Creating database from scratch?
03-21 14:36:44.082: V/SpotTheStation(20034): android.database.sqlite.SQLiteException: table countries already exists (code 1): , while compiling: create table countries(_id integer primary key autoincrement, country text);
现在,这让我感到困扰,我在其他一些应用程序上具有相同的 DB 结构(相同的逻辑,一个非静态 OpenHelper 和一个用于访问 dB 内容的静态管理器),并且一切正常,不知道是什么导致这里的问题。
我会很感激一些帮助。
快速编辑
为了更清楚一点,第一次启动(应用程序第一次运行)时getCountries
确实有效,后续运行将导致异常。卸载重新安装过程使其再次工作,然后在第二次运行时死亡。
编辑二号
根据要求,这是 OpenHelper 的完整代码:
public class CountryDbHelper extends SQLiteOpenHelper {
/**
* This path is hardcoded, during the first time application opens
* we copy a database file from the assets folder into this folder.
*/
public final static String DB_PATH = "/data/data/com.nasa.apps.spotthestation/databases/";
private static final int DB_VERSION = 2;
public static String DB_NAME = "countries";
public static final String TABLE_COUNTRIES = "countries";
public static final String TABLE_REGIONS = "regions";
public static final String DEFAULT_SORT_ORDER = "_id";
public static final String [] PROJECTION_COUNTRIES = {
"_id",
"country"
};
public static final String [] PROJECTION_REGIONS = {
"_id",
"country",
"region"
};
/**
* Table with only countries
*/
private static final String CREATE_TABLE_COUNTRIES = "create table " + TABLE_COUNTRIES
+ "(_id integer primary key autoincrement, "
+ "country text);"
;
/**
* Table that contains regions per country
*/
private static final String CREATE_TABLE_REGIONS = "create table " + TABLE_REGIONS
+ "(_id integer primary key autoincrement, "
+ "country text, "
+ "region text);"
;
/**
* Not used for now
*/
private static final String CREATE_TABLE_CITIES = "create table " + TABLE_COUNTRIES
+ "(_id integer primary key autoincrement, "
+ "country text, "
+ "region text, "
+ "city text);"
;
public CountryDbHelper(Context context, CursorFactory factory,
int version) {
super(context, DB_NAME, factory, version);
}
public CountryDbHelper (Context context) {
super(context, DB_NAME, null, DB_VERSION );
}
@Override
public void onCreate(SQLiteDatabase db) {
Constants.logMessage("Creating database from scratch?");
//Create both of the tables as part of the databases
db.execSQL(CREATE_TABLE_COUNTRIES);
db.execSQL(CREATE_TABLE_REGIONS);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Constants.logMessage("Upgrading db from " + oldVersion + " to new version: " + newVersion);
db.execSQL("DROP TABLE IF EXISTS " + TABLE_COUNTRIES);
db.execSQL("DROP TABLE IF EXISTS " + TABLE_REGIONS);
onCreate(db);
}
}
另外,我注意到的一件事是 /data/data/packageName/databases/ 上的数据库文件没有“sqlite_sequence”文件,该文件通常存储数据库中每个表的行数。我认为问题可能是该文件丢失,因为这两个表使用“主键自动增量”,并且我相信它依赖于知道插入时要使用的下一个 _id 是什么。任何人都可以证实这一点?
再次编辑以防万一,我继续将数据类型从“_id”字段更改autoincrement
为简单numeric
,因为我不打算向数据库添加更多数据,这是一个只读意图,但它仍然强制关闭第二次发射。
谢谢!