Почему onUpgrade () не используется в базе данных Android sqlite?

Я хочу обновить свою базу данных, когда она установлена ​​на мой эмулятор Android. Я установил версию db в свой DbHelper, который наследует от SQLiteOpenHelper +1.

Однако, когда загружается мой 1-й актив, я создаю экземпляр своего DbHelper, который я ожидал бы, что SQLiteOpenHelper вызовет onUpgrade, поскольку версия db теперь более новая. Однако он никогда не называется. Мне интересно, есть ли что-то, чего я не вижу. Где версия, которую DbHelper использует для сравнения с новой версией? Почему это не работает?

Я фактически копирую базу данных из папки ресурсов в папку данных, а не повторно создаю схему.

public class DbHelper extends SQLiteOpenHelper { private static final String TAG = "DbHelper"; static final String DB_NAME = "caddata.sqlite"; static final int DB_VERSION = 4; private static String DB_PATH = ""; private Context myContext; private SQLiteDatabase myDataBase; public DbHelper(Context context) { super(context, DB_NAME, null, DB_VERSION); this.myContext = context; DB_PATH = "/data/data/" + context.getApplicationContext().getPackageName() + "/databases/"; } public DbHelper open() throws SQLException { myDataBase = getWritableDatabase(); Log.d(TAG, "DbHelper Opening Version: " + this.myDataBase.getVersion()); return this; } @Override public synchronized void close() { if (myDataBase != null) myDataBase.close(); super.close(); } @Override public void onCreate(SQLiteDatabase db) { Log.d(TAG, "onCreate called"); try { createDataBase(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { if ( newVersion > oldVersion) { Log.d(TAG, "New database version exists for upgrade."); try { Log.d(TAG, "Copying database..."); copyDataBase(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public void createDataBase() throws IOException { boolean dbExist = checkDataBase(); if (!dbExist) { try { copyDataBase(); } catch (IOException e) { throw new Error("Error copying database"); } } openDataBaseForRead(); } private boolean checkDataBase() { SQLiteDatabase checkDB = null; try { String myPath = DB_PATH + DB_NAME; checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY | SQLiteDatabase.NO_LOCALIZED_COLLATORS); Log.d(TAG, "db exists"); } catch (SQLiteException e) { // database does't exist yet. Log.d(TAG, "db doesn't exist"); } if (checkDB != null) { checkDB.close(); } return checkDB != null ? true : false; } private void copyDataBase() throws IOException { // Open your local db as the input stream InputStream myInput = myContext.getAssets().open(DB_NAME); // Path to the just created empty db String outFileName = DB_PATH + DB_NAME; // Open the empty db as the output stream OutputStream myOutput = new FileOutputStream(outFileName); // transfer bytes from the inputfile to the outputfile byte[] buffer = new byte[2048]; int length; while ((length = myInput.read(buffer)) > 0) { myOutput.write(buffer, 0, length); } // Close the streams myOutput.flush(); myOutput.close(); myInput.close(); myDataBase.setVersion(DB_VERSION); } public void openDataBaseForRead() throws SQLException { // Open the database String myPath = DB_PATH + DB_NAME; myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY); } public void openDataBaseForWrite() throws SQLException { // Open the database String myPath = DB_PATH + DB_NAME; myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE | SQLiteDatabase.NO_LOCALIZED_COLLATORS ); } } 

Solutions Collecting From Web of "Почему onUpgrade () не используется в базе данных Android sqlite?"

Это фрагмент кода из источника SQLiteOpenHelper.getWritableDatabase() :

 int version = db.getVersion(); if (version != mNewVersion) { db.beginTransaction(); try { if (version == 0) { onCreate(db); } else { if (version > mNewVersion) { onDowngrade(db, version, mNewVersion); } else { onUpgrade(db, version, mNewVersion); } } db.setVersion(mNewVersion); db.setTransactionSuccessful(); } finally { db.endTransaction(); } } onOpen(db); 

Как вы можете видеть, onCreate() или onUpgrade() вызывается в вызове getWritableDatabase() . Вы должны использовать эти вызовы всякий раз, когда вам нужен экземпляр SQLiteDatabase . Вы не должны использовать свои собственные методы, за исключением случаев, когда они являются оболочками getReadableDatabase метода getWritableDatabase или getReadableDatabase .

Документация гласит:

База данных фактически не создается или не открывается до тех пор, пока не вызывается одна из getWritableDatabase () или getReadableDatabase ().

Я вижу, что вы внедрили свои собственные методы для получения базы данных: openDataBaseForRead() и openDataBaseForWrite() . Плохо 😉

Я выяснил проблему. Эта проблема возникает только при копировании db из активов. Db в папке с активами имеет версию по умолчанию 0. Поэтому, когда вы вызываете вспомогательный помощник базы данных с номером версии (скажем, 1), а затем перезаписываете его с именем в активах, номер версии сбрасывается на 0.

И когда вы вызываете db.getReadableDatabase () или db.getWriteableDatabase, который должен вызывать метод onUpgrade, он терпит неудачу, потому что номер версии 0, который должен быть новой базой данных. Вы можете посмотреть исходный код SqliteOpenHelper. Он запускает метод onUpgrade только тогда, когда версия больше нуля, а текущая версия больше старой.

`

 db.beginTransaction(); try { //Skips updating in your case if (version == 0) { onCreate(db); } else { if (version > mNewVersion) { onDowngrade(db, version, mNewVersion); } else { onUpgrade(db, version, mNewVersion); } } db.setVersion(mNewVersion); db.setTransactionSuccessful(); } finally { db.endTransaction(); } 

`

Так вот что я сделал, чтобы преодолеть эту проблему. Его нет, где идеальное решение, но оно работает. В основном вам нужно обновить версию db, прежде чем вы вызовете супер метод класса SQLiteOpenHelper (конструктор вашего менеджера баз данных).

`

 try { String myPath = MyApplication.context.getDatabasePath(DATABASE_NAME).toString(); //open a database directly without Sqliteopenhelper SQLiteDatabase myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE | SQLiteDatabase.NO_LOCALIZED_COLLATORS); //if the version is default 0 the update the version if (myDataBase.getVersion() == 0) { //update the database version to the previous one myDataBase.execSQL("PRAGMA user_version = " + 1); } //Close DataBase myDataBase.close(); } catch (Exception e) { //Do Nothing a fresh install happened } 

`

PS: Я знаю, что ответ задерживается, но может помочь кому-то вроде меня, который искал это решение