最終編集、「解決済み」の問題
したがって、受け入れられた回答に従って最終的に行ったことは、データベースのバージョンをパラメーターとして使用するコンストラクターを削除しましたが、それでも例外が発生しました。また、提案されているように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 にアクセスしようとするたびに発生します。アプリの有効期間を通じて 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アクセス呼び出しで実行されるように見える作成ステートメントは次のとおりです。
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
起動時 (アプリの初回実行時) に動作し、その後の実行では例外が発生します。アンインストールと再インストールのプロセスで再び機能するようになり、2 回目の実行で停止します。
編集番号 2
リクエストに応じて、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);
}
}
また、私が気づいたことの 1 つは、/data/data/packageName/databases/ のデータベース ファイルに「sqlite_sequence」ファイルがないことです。これは通常、データベースの各テーブルごとの行数を格納します。2 つのテーブルは「PRIMARY KEY autoincrement」を使用しているため、問題はそのファイルが欠落している可能性があると思います。挿入時に使用する次の _id が何であるかを知るには、それに依存していると思います。誰でもこれを確認できますか?
再度編集念のため、データベースにデータを追加する予定がないため、データ型を「_id」フィールドautoincrement
から単純numeric
に変更しました。これは読み取り専用の意図ですが、それでも強制的に閉じます二度目の打ち上げ。
ありがとう!