1

最終編集、「解決済み」の問題

したがって、受け入れられた回答に従って最終的に行ったことは、データベースのバージョンをパラメーターとして使用するコンストラクターを削除しましたが、それでも例外が発生しました。また、提案されているように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に変更しました。これは読み取り専用の意図ですが、それでも強制的に閉じます二度目の打ち上げ。

ありがとう!

4

2 に答える 2

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);
            }       
        }
于 2013-03-21T23:30:13.490 に答える