最终编辑,问题“已解决”
所以我最终按照接受的答案做了,我删除了将数据库版本作为params的构造函数,但仍然导致了异常。所以同样建议,我添加了一个try{} catch{}
块来捕获问题,让我告诉你,它仍然显示抛出异常,只是这次它不会使应用程序崩溃。幸运的是,尽管它似乎在创建数据库时遇到了问题,但它允许我将db内容加载到应用程序中,所以我现在对该日志消息很好:)
这是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时都会发生这种情况,我有一个单独的静态类,可以在整个应用程序生命周期内处理数据库访问,我通过以下方式将上下文传递给它:
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()
。
这是似乎在每次数据库访问调用上执行的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);
现在,这就困扰我了,我在其他一些应用程序(相同的逻辑,一个非静态的OpenHelper和一个静态管理器来访问dB内容)上有相同的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”文件,该文件通常存储数据库中每个表的行数。我认为问题可能是该文件丢失,因为这两个表使用“PRIMARY KEY autoincrement”,我相信它依赖于它来知道插入时使用的下一个_id是什么。任何人都可以证实这一点?
再次编辑以防万一,我继续将数据类型从autoincrement
更改为“_id”字段上的numeric
,因为我不打算添加更多的数据到数据库,它是一个只读的意图,但它仍然强制关闭第二次启动。
谢谢!
答案 0 :(得分:2)
您是否在此类super(context, DATABASE_NAME, null, DATABASE_VERSION);
private static class DatabaseHelper extends SQLiteOpenHelper{
DatabaseHelper(Context context){
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db){
try{
db.execSQL(TABLE_CREATE);
} catch (SQLException e){
e.printStackTrace();
}
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){
db.execSQL("DROP TABLE IF EXISTS "+DATABASE_TABLE);
onCreate(db);
}
}
答案 1 :(得分:0)
我遇到了这个问题,添加了<&lt ;;>>到DROP TABLE行的末尾解决了我的问题。
db.execSQL("DROP TABLE IF EXISTS " + TABLE_COUNTRIES + ";");
db.execSQL("DROP TABLE IF EXISTS " + TABLE_REGIONS + ";");
不要忘记在需要时更改版本。