为什么在Android sqlite数据库上没有调用onUpgrade()?

jaf*_*ffa 17 sqlite android

我想在我的android模拟器上安装数据库时升级它.我在我的DbHelper中设置了db版本,它继承自SQLiteOpenHelper到+1.

但是,当我的第一个活动加载时,我实例化我的DbHelper,我希望SQLiteOpenHelper调用onUpgrade,因为db版本现在更新了.但它永远不会被称为.我想知道是否有我遗失的东西.DbHelper使用的版本在哪里存储以与新版本进行比较?为什么这不起作用?

我实际上是将数据库从assets文件夹复制到数据文件夹,而不是重新创建模式.

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 );
    }


}
Run Code Online (Sandbox Code Playgroud)

kde*_*iry 29

这是来自以下来源的代码段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);
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,在调用中调用onCreate()onUpgrade()调用getWritableDatabase().每当需要实例时,您必须使用这些调用SQLiteDatabase.你不应该使用自己的方法,除非它们是getWritableDatabase或者getReadableDatabase方法的包装器.


paw*_*eba 12

文件说:

在调用getWritableDatabase()或getReadableDatabase()之一之前,实际上不会创建或打开数据库.

我看到你已经实现了自己的获取数据库的方法:openDataBaseForRead()openDataBaseForWrite().那很糟 ;-)


Bui*_*d3r 5

我已经解决了问题。仅当您从资产复制数据库时,才会出现此问题。Assets文件夹中的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();
}
Run Code Online (Sandbox Code Playgroud)

`

因此,这就是我为克服此问题所做的工作。它没有完美的解决方案,但是可以正常工作。基本上,在调用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
   }
Run Code Online (Sandbox Code Playgroud)

`

PS:我知道答案来晚了,但是对于像我这样正在寻找特定解决方案的人可能会有所帮助