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

2023-09-06 13:08:16 作者:山河相送

我想,当它被安装到我的Andr​​oid模拟器来升级我的数据库。 我已经设置了分贝版本我DbHelper继承于SQLiteOpenHelper +1。

然而,当我第一次活动的负载,我实例我DbHelper,我希望SQLiteOpenHelper打电话onUpgrade为DB版本现已更新。然而,它永远不会被调用。我不知道是否有我丢失的东西。哪里是该DbHelper使用存储比较相对于​​新版本的版本?这是为什么不工作?

我其实复制数据库从资产文件夹到数据文件夹,而不是重新创建模式。

 公共类DbHelper扩展SQLiteOpenHelper {
    私有静态最后字符串变量=DbHelper;

    静态最后弦乐DB_NAME =caddata.sqlite;
    静态最终诠释DB_VERSION = 4;

    私有静态字符串DB_PATH =;
    私人语境myContext;
    私人SQLiteDatabase MyDatabase的;

    公共DbHelper(上下文的背景下){
        超(背景下,DB_NAME,空,DB_VERSION);
        this.myContext =背景;

        DB_PATH =/数据/数据​​/
                + context.getApplicationContext()。getPackageName()
                +/数据库/;
    }

    公共DbHelper的open()抛出的SQLException {
        MyDatabase的= getWritableDatabase();

        Log.d(TAG,DbHelper开放版本:+ this.myDataBase.getVersion());
        回到这一点;
    }

    @覆盖
    市民同步无效的close(){

        如果(MyDatabase的!= NULL)
            myDataBase.close();

        super.close();

    }

    @覆盖
    公共无效的onCreate(SQLiteDatabase DB){
        Log.d(TAG的onCreate名为);

        尝试 {
            的CreateDatabase();
        }赶上(IOException异常E){
            // TODO自动生成的catch块
            e.printStackTrace();
        }
    }

    @覆盖
    公共无效onUpgrade(SQLiteDatabase分贝,INT oldVersion,诠释静态网页){
        如果(动态网页> oldVersion)
        {
            Log.d(TAG,新的数据库版本存在升级。);
            尝试 {
                Log.d(TAG,复制数据库......);
                copyDataBase();
            }赶上(IOException异常E){
                // TODO自动生成的catch块
                e.printStackTrace();
            }
        }
    }

    公共无效的CreateDatabase()抛出IOException异常{

        布尔dbExist = checkDataBase();

        如果(!dbExist){

            尝试 {
                copyDataBase();
            }赶上(IOException异常E){
                抛出新的错误(错误复制数据库);
            }
        }

        openDataBaseForRead();
    }


    私人布尔checkDataBase(){

        SQLiteDatabase CHECKDB = NULL;

        尝试 {
            字符串mypath中= DB_PATH + DB_NAME;
            CHECKDB = SQLiteDatabase.openDatabase(mypath中,空,
                    SQLiteDatabase.OPEN_READONLY
                            | SQLiteDatabase.NO_LOCALIZED_COLLATORS);
            Log.d(TAG,分贝存在);
        }赶上(SQLiteException E){
            //数据库的简化版,存在。
            Log.d(TAG,分贝不存在);

        }

        如果(CHECKDB!= NULL){
            checkDB.close();
        }

        返回CHECKDB!= NULL?真假;
    }


    私人无效copyDataBase()抛出IOException异常{

        //打开本地数据库作为输入流
        InputStream的myInput = myContext.getAssets()开(DB_NAME)。

        //路径刚刚创建的空分贝
        字符串outFileName = DB_PATH + DB_NAME;

        //打开空分贝的输出流
        的OutputStream myOutput =新的FileOutputStream(outFileName);

        //传输的字节从inputfile中的OUTPUTFILE
        byte []的缓冲区=新的字节[2048];
        INT长;
        而((长度= myInput.read(缓冲液))大于0){
            myOutput.write(缓冲液,0,长度);
        }

        //关闭流
        myOutput.flush();
        myOutput.close();
        myInput.close();

        myDataBase.setVersion(DB_VERSION);
    }

    公共无效openDataBaseForRead()抛出的SQLException {

        //打开数据库
        字符串mypath中= DB_PATH + DB_NAME;
        MyDatabase的= SQLiteDatabase.openDatabase(mypath中,空,SQLiteDatabase.OPEN_READONLY);
    }

    公共无效openDataBaseForWrite()抛出的SQLException {

        //打开数据库
        字符串mypath中= DB_PATH + DB_NAME;
        MyDatabase的= SQLiteDatabase.openDatabase(mypath中,空,SQLiteDatabase.OPEN_READWRITE | SQLiteDatabase.NO_LOCALIZED_COLLATORS);
    }


}
 

解决方案

这是从 SQLiteOpenHelper.getWritableDatabase源() A code片断:

  INT版本= db.getVersion();
如果(版本!= mNewVersion){
    db.beginTransaction();
    尝试 {
        如果(版本== 0){
            的onCreate(DB);
        } 其他 {
            如果(版本> mNewVersion){
                onDowngrade(DB,版本,mNewVersion);
            } 其他 {
                onUpgrade(DB,版本,mNewVersion);
            }
        }
        db.setVersion(mNewVersion);
        db.setTransactionSuccessful();
    } 最后 {
        db.endTransaction();
    }
}

的OnOpen(DB);
 
Android学习如何创建数据库 SQLite onCreate,onUpgrade方法 和SQLiteStudio的使用

正如你所看到的,的onCreate() onUpgrade()呼叫中被称为 getWritableDatabase()。 你当你需要 SQLiteDatabase 的实例使用这些调用。你不应该用你自己的方法,除非它们是包装约于 getWritableDatabase getReadableDatabase 方法。

I want to upgrade my database when it is installed onto my android emulator. I have set the db version in my DbHelper which inherits from SQLiteOpenHelper to +1.

However, when my 1st activity loads, I instantiate my DbHelper, which I would expect SQLiteOpenHelper to call onUpgrade as the db version is now newer. However it is never called. I'm wondering if there is something I am missing. Where is the version that the DbHelper is using stored to compare against the new version? Why is this not working?

I am actually copying the database from the assets folder into the data folder rather than re-creating the schema.

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


}

解决方案

This is a code snippet from the source of 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);

As you can see, the onCreate() or onUpgrade() are called within the call to getWritableDatabase(). You have to use these calls whenever you need an instance of SQLiteDatabase. You shouldn't use your own methods, except if they are wrappers arround the getWritableDatabase or getReadableDatabase method.