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

标签 android sqlite

我想在我的安卓模拟器上安装我的数据库时升级它。 我已将继承自 SQLiteOpenHelper 的 DbHelper 中的 db 版本设置为 +1。

但是,当我的第一个 Activity 加载时,我实例化了我的 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 );
    }


}

最佳答案

这是来自SQLiteOpenHelper.getWritableDatabase()的代码 fragment :

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 的实例时,您必须使用这些调用。您不应该使用自己的方法,除非它们是围绕 getWritableDatabasegetReadableDatabase 方法的包装器。

关于android - 为什么在 Android sqlite 数据库上没有调用 onUpgrade()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7647566/

相关文章:

android - 无法在我的国家使用 GCM

java - 我无法将数据插入我的数据库

java - Android中的SQLite如何更新特定行

sqlite3 缩短浮点值

go - 如何使 func main() 中设置的数据库实例对其他包可用?

java - Sqlite 按距离现在最近的时间排序

android - 与 ESP8266-01 上设置的服务器通信的 TCP 客户端

android - 如何在抖动中显示横向和纵向的不同布局

android - 静态 Activity 生成器?

android - 创建 "Battery usage" Intent android