关于升级方法没有在Android sqlite中被调用 [英] On upgrade method not getting called in android sqlite

查看:63
本文介绍了关于升级方法没有在Android sqlite中被调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在我的应用程序中使用预先填充的sqlite数据库,并且试图在我的android应用程序中更新数据库,但是当我增加版本号时,不会调用onUpgrade方法.我尝试了谷歌搜索,在stackoverflow上进行了搜索,但没有任何帮助.如果在构造函数中取消注释this.getReadableDatabase(),则会调用onUpgrade方法,但无法查询数据并返回错误.

I'm using prepopulated sqlite database in my app and i'm trying to update my database in my android application but the onUpgrade method doesn't get called when I increment the version number. i tried googling, searched on stackoverflow but nothing helped. if I uncomment this.getReadableDatabase() in my constructor the onUpgrade method gets called but I can't query the data and returns error.

这是我的代码.

     public class DatabaseHelper extends SQLiteOpenHelper {

        private  static final String DB_NAME = "dictionary.db";
        private static final int DB_VERSION = 1;
        private String DB_PATH = null;
        private  static final String TABLE_DICTIONARY = "dictionary";
        private  static final String TABLE_BOOKMARK= "bookmark";
        private static final String COL_ID = "id";
        private static final String COL_WORD = "word";
        private static final String COL_DEFINITION = "definition";
        private Context mcontext;
        private SQLiteDatabase mDatabase;


        public DatabaseHelper( Context context) {
            super(context, DB_NAME, null, DB_VERSION);
            this.mcontext = context;
            this.DB_PATH = "/data/data/" + context.getPackageName() + "/" + "databases/";
            //this.getReadableDatabase();
        }

        public void createDataBase() throws IOException {

            boolean dbExist = checkDataBase();
            if (!dbExist) {
                this.getReadableDatabase();
                try {
                    mcontext.deleteDatabase(DB_NAME);
                    copyDataBase();
                } catch (IOException e) {
                    throw new Error("Error copying database");
                }
            }
        }

        public boolean checkDataBase() {
            SQLiteDatabase checkDB = null;
            try {
                String myPath = DB_PATH + DB_NAME;
                checkDB = SQ

LiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
        } catch (SQLiteException e) {
            e.printStackTrace();
        }
        if (checkDB != null) {
            checkDB.close();
        }
        return checkDB != null ? true : false;
    }

    private void copyDataBase() throws IOException {

        InputStream myInput = mcontext.getAssets().open(DB_NAME);
        String outFileName = DB_PATH + DB_NAME;
        OutputStream myOutput = new FileOutputStream(outFileName);
        byte[] buffer = new byte[1024];
        int length;
        while ((length = myInput.read(buffer)) > 0) {
            myOutput.write(buffer, 0, length);
        }
        myOutput.flush();
        myOutput.close();
        myInput.close();
    }

    public void openDatabase() throws SQLException {
        String myPath = DB_PATH + DB_NAME;
        mDatabase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);
    }

    @Override
    public synchronized void close() {
        if (mDatabase != null)
            mDatabase.close();
        super.close();
    }

         @Override
    public void onCreate(SQLiteDatabase db) {

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

        if (newVersion > oldVersion) {
            try {
                copyDataBase();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        Log.d(TAG, "onUpgrade:called ");
    }
}

推荐答案

我相信您的问题是您没有使用 SQLiteOpenHelper 的方法之一( getWritableDatabse getReadableDatabase )打开数据库.

I believe that your issue is that you don't use one of the SQLiteOpenHelper's methods (getWritableDatabse or getReadableDatabase) to open the database.

您可以使用 SQLiteDatabase OPEN 方法.哪个不进行版本检查和设置.

Rather you use the SQLiteDatabase's OPEN method. Which doesn't do the version check and set.

如果我在构造函数中取消注释this.getReadableDatabase() 调用了onUpgrade方法,但是我无法查询数据并返回 错误.

If I uncomment this.getReadableDatabase() in my constructor the onUpgrade method gets called but I can't query the data and returns error.

引入 getReadableDatabase ,然后进行检查并尝试复制较新的版本,但是较旧的版本处于打开状态,因此可能会导致冲突.

Introducing the getReadableDatabase, then does the check and attempts to copy the newer version, but the older version is open and so you likely get a conflict as a result.

您可能会找到问题的答案

You may find the answers to the question Which methods can be used to manage differing versions of pre-existing databases? helpful (perhaps the 2nd).

以下工作示例利用了链接的答案中的代码,但是基于问题的代码和数据库(可以确定).

The following working example utilises the code from the linked answer but is based upon the code and database from the question (as is ascertainable).

核心基础类是 DatabaseAssetHandler.java ,其中包括许多用于检查和复制数据库的静态方法,尤其是作为文件而不是作为SQLite数据库的

The core underlying class is DatabaseAssetHandler.java, which includes a number of static methods for checking and copying the database, all notably as a file rather than as an SQLite database.

SQLiteOpenHelper的子类,基于问题的 DatabaseHelper.java 类,但利用DatabaseAssethandler方法再次从数据库文件版本检查编码版本(无需使用onUpgrade方法以及onCreate方法)

A subclass of SQLiteOpenHelper, based upon the question's DatabaseHelper.java class but utilising the DatabaseAssethandler methods to check the coded version againast the database file version (negating the need to use the onUpgrade method and also the onCreate method)

最后,该示例包括一个活动 MainActivity.java ,您通常会找到它.该类还从数据库中提取所有行,并将Cursor转储到日志中.

Finally the example includes an Activity, MainActivity.java as you'd typically find. This class additionally extracts all rows from the database and dumps the Cursor to the log.

public class DatabaseAssetHandler {

    static final String[] tempfiles = new String[]{"-journal","-wal","-shm"}; // temporary files to rename
    public static final String backup = "-backup"; //value to be appended to file name when renaming (psuedo delete)
    public static final  int OUCH = -666666666;

    /**
     * Check if the database already exists. NOTE will create the databases folder is it doesn't exist
     * @return true if it exists, false if it doesn't
     */
    public static boolean checkDataBase(Context context, String dbname) {

        File db = new File(context.getDatabasePath(dbname).getPath()); //Get the file name of the database
        Log.d("DBPATH","DB Path is " + db.getPath()); //TODO remove if publish App
        if (db.exists()) return true; // If it exists then return doing nothing

        // Get the parent (directory in which the database file would be)
        File dbdir = db.getParentFile();
        // If the directory does not exits then make the directory (and higher level directories)
        if (!dbdir.exists()) {
            db.getParentFile().mkdirs();
            dbdir.mkdirs();
        }
        return false;
    }

    /**
     * Copy database file from the assets folder
     * (long version caters for asset file name being different to the database name)
     * @param context           Context is needed to get the applicable package
     * @param dbname            name of the database file
     * @param assetfilename     name of the asset file
     * @param deleteExistingDB  true if an existing database file should be deleted
     *                              note will delete journal and wal files
     *                              note doen't actually delete the files rater it renames
     *                              the files by appended -backup to the file name
     *                              SEE/USE clearForceBackups below to delete the renamed files
     */
    public static void copyDataBase(Context context, String dbname, String assetfilename, boolean deleteExistingDB, int version) {

        checkpointIfWALEnabled(context,dbname);
        final String TAG = "COPYDATABASE";
        int stage = 0, buffer_size = 4096, blocks_copied = 0, bytes_copied = 0;
        File f = new File(context.getDatabasePath(dbname).toString());
        InputStream is;
        OutputStream os;

        /**
         * If forcing then effectively delete (rename) current database files
         */
        if (deleteExistingDB) {
            f.renameTo(context.getDatabasePath(dbname + backup));
            for (String s: tempfiles) {
                File tmpf = new File(context.getDatabasePath(dbname + s).toString());
                if (tmpf.exists()) {
                    tmpf.renameTo(context.getDatabasePath(dbname + s + backup));
                }
            }
        }

        //Open your local db as the input stream
        Log.d(TAG,"Initiated Copy of the database file " + assetfilename + " from the assets folder."); //TODO remove if publishing
        try {
            is = context.getAssets().open(assetfilename); // Open the Asset file
            stage++;
            Log.d(TAG, "Asset file " + assetfilename + " found so attmepting to copy to " + f.getPath()); //TODO remove if publishing

            os = new FileOutputStream(f);
            stage++;
            //transfer bytes from the inputfile to the outputfile
            byte[] buffer = new byte[buffer_size];
            int length;
            while ((length = is.read(buffer)) > 0) {
                blocks_copied++;
                Log.d(TAG, "Attempting copy of block " + String.valueOf(blocks_copied) + " which has " + String.valueOf(length) + " bytes."); //TODO remove if publishing
                os.write(buffer, 0, length);
                bytes_copied += length;
            }
            stage++;
            Log.d(TAG,
                    "Finished copying Database " + dbname +
                            " from the assets folder, to  " + f.getPath() +
                            String.valueOf(bytes_copied) + "were copied, in " +
                            String.valueOf(blocks_copied) + " blocks of size " +
                            String.valueOf(buffer_size) + "."
            ); //TODO remove if publishing
            //Close the streams
            os.flush();
            stage++;
            os.close();
            stage++;
            is.close();
            Log.d(TAG, "All Streams have been flushed and closed.");
            if (version > 0) {
                setVersion(context,dbname,version);
            }
        } catch (IOException e) {
            String exception_message = "";
            e.printStackTrace();
            switch (stage) {
                case 0:
                    exception_message = "Error trying to open the asset " + dbname;
                    break;
                case 1:
                    exception_message = "Error opening Database file for output, path is " + f.getPath();
                    break;
                case 2:
                    exception_message = "Error flushing written database file " + f.getPath();
                    break;
                case 3:
                    exception_message = "Error closing written database file " + f.getPath();
                    break;
                case 4:
                    exception_message = "Error closing asset file " + f.getPath();

            }
            throw new RuntimeException("Unable to copy the database from the asset folder." + exception_message + " see starck-trace above.");
        }
    }

    /**
     * Copy the databsse from the assets folder where asset name and dbname are the same
     * @param context
     * @param dbname
     * @param deleteExistingDB
     */
    public static void copyDataBase(Context context, String dbname, boolean deleteExistingDB, int version) {
        copyDataBase(context, dbname,dbname,deleteExistingDB, version);
    }

    /**
     * Get the SQLite_user_vesrion from the DB in the asset folder
     *
     * @param context           needed to get the appropriate package assets
     * @param assetfilename     the name of the asset file (assumes/requires name matches database)
     * @return                  the version number as stored in the asset DB
     */
    public static int getVersionFromDBInAssetFolder(Context context, String assetfilename) {
        InputStream is;
        try {
            is = context.getAssets().open(assetfilename);
        } catch (IOException e) {
            return OUCH;
        }
        return getDBVersionFromInputStream(is);
    }

    /**
     * Get the version from the database itself without opening the database as an SQliteDatabase
     * @param context   Needed to ascertain package
     * @param dbname    the name of the dataabase
     * @return          the version number extracted
     */
    public static int getVersionFromDBFile(Context context, String dbname) {
        InputStream is;
        try {
            is = new FileInputStream(new File(context.getDatabasePath(dbname).toString()));
        } catch (IOException e) {
            return OUCH;
        }
        return getDBVersionFromInputStream(is);
    }

    /**
     * Get the Database Version (user_version) from an inputstream
     *  Note the inputstream is closed
     * @param is    The Inputstream
     * @return      The extracted version number
     */
    private static int getDBVersionFromInputStream(InputStream is) {
        int rv = -1, dbversion_offset = 60, dbversion_length = 4 ;
        byte[] dbfileheader = new byte[64];
        byte[] dbversion = new byte[4];
        try {
            is.read(dbfileheader);
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
            return rv;
        }

        for (int i = 0; i < dbversion_length; i++ ) {
            dbversion[i] = dbfileheader[dbversion_offset + i];
        }
        return ByteBuffer.wrap(dbversion).getInt();
    }

    /**
     * Check to see if the asset file exists
     *
     * @param context           needed to get the appropriate package
     * @param assetfilename     the name of the asset file to check
     * @return                  true if the asset file exists, else false
     */
    public static boolean ifAssetFileExists(Context context, String assetfilename) {
        try {
            context.getAssets().open(assetfilename);
        } catch (IOException e) {
            return false;
        }
        return true;
    }


    /**
     * Delete the backup
     * @param context
     * @param dbname
     */
    public static void clearForceBackups(Context context, String dbname) {
        String[] fulllist = new String[tempfiles.length + 1];

        for (int i = 0;i < tempfiles.length; i++) {
            fulllist[i] = tempfiles[i];
        }
        fulllist[tempfiles.length] = ""; // Add "" so database file backup is also deleted
        for (String s: fulllist) {
            File tmpf = new File(context.getDatabasePath(dbname + s + backup).toString());
            if (tmpf.exists()) {
                tmpf.delete();
            }
        }
    }

    /**
     *
     * @param context   The context so that the respective package is used
     * @param dbname    The name of the database (the old will have -backup appended)
     * @param table     The table from which to copy the data
     */
    public static void restoreTable(Context context, String dbname, String table) {
        ContentValues cv = new ContentValues();
        SQLiteDatabase dbnew = SQLiteDatabase.openDatabase(context.getDatabasePath(dbname).toString(), null,SQLiteDatabase.OPEN_READWRITE);
        SQLiteDatabase dbold = SQLiteDatabase.openDatabase(context.getDatabasePath(dbname + backup).toString(),null,SQLiteDatabase.OPEN_READONLY);
        Cursor csr = dbold.query(table,null,null,null,null,null,null);
        dbnew.beginTransaction();
        while (csr.moveToNext()) {
            cv.clear();
            int offset = 0;
            for (String column: csr.getColumnNames()) {
                switch (csr.getType(offset++)){
                    case Cursor.FIELD_TYPE_NULL:
                        break;
                    case Cursor.FIELD_TYPE_INTEGER:
                        cv.put(column,csr.getLong(csr.getColumnIndex(column)));
                        break;
                    case Cursor.FIELD_TYPE_FLOAT:
                        cv.put(column,csr.getFloat(csr.getColumnIndex(column)));
                        break;
                    case Cursor.FIELD_TYPE_STRING:
                        cv.put(column,csr.getString(csr.getColumnIndex(column)));
                        break;
                    case Cursor.FIELD_TYPE_BLOB:
                        cv.put(column,csr.getBlob(csr.getColumnIndex(column)));
                }
            }
            dbnew.insert(DatabaseHelper.TABLE_BOOKMARK,null,cv);
        }
        dbnew.setTransactionSuccessful();
        dbnew.endTransaction();
        csr.close();
        dbnew.close();
        dbold.close();
    }

    private static void checkpointIfWALEnabled(Context context, String dbname) {
        final String TAG = "WALCHKPNT";
        Cursor csr;
        int wal_busy = -99, wal_log = -99, wal_checkpointed = -99;
        if (!new File(context.getDatabasePath(dbname).getPath()).exists()) {
            return;
        }
        SQLiteDatabase db = SQLiteDatabase.openDatabase(context.getDatabasePath(dbname).getPath(),null,SQLiteDatabase.OPEN_READWRITE);
        csr = db.rawQuery("PRAGMA journal_mode",null);
        if (csr.moveToFirst()) {
            String mode = csr.getString(0);
            //Log.d(TAG, "Mode is " + mode);
            if (mode.toLowerCase().equals("wal")) {
                csr = db.rawQuery("PRAGMA wal_checkpoint",null);
                if (csr.moveToFirst()) {
                    wal_busy = csr.getInt(0);
                    wal_log = csr.getInt(1);
                    wal_checkpointed = csr.getInt(2);
                }
                //Log.d(TAG,"Checkpoint pre checkpointing Busy = " + String.valueOf(wal_busy) + " LOG = " + String.valueOf(wal_log) + " CHECKPOINTED = " + String.valueOf(wal_checkpointed) );
                csr = db.rawQuery("PRAGMA wal_checkpoint(TRUNCATE)",null);
                csr.getCount();
                csr = db.rawQuery("PRAGMA wal_checkpoint",null);
                if (csr.moveToFirst()) {
                    wal_busy = csr.getInt(0);
                    wal_log = csr.getInt(1);
                    wal_checkpointed = csr.getInt(2);
                }
                //Log.d(TAG,"Checkpoint post checkpointing Busy = " + String.valueOf(wal_busy) + " LOG = " + String.valueOf(wal_log) + " CHECKPOINTED = " + String.valueOf(wal_checkpointed) );
            }
        }
        csr.close();
        db.close();
    }

    private static void setVersion(Context context, String dbname, int version) {
        SQLiteDatabase db = SQLiteDatabase.openDatabase(context.getDatabasePath(dbname).getPath(),null,SQLiteDatabase.OPEN_READWRITE);
        db.setVersion(version);
        db.close();

    }
}

  • 请注意,并非所有方法都可以使用.
  • 注释已修改(2019-05-08)以在将资产文件调用复制到新的 setVersion 方法之后专门设置版本号.
  • 已修改注释(2019-05-08)以在复制之前调用新的checkpointIfWALEnabled方法,以便对数据库进行检查.
    • Note that not all methods are utilised.
    • Note modified (2019-05-08) to specifically set the version number after the copy of the asset file call to new setVersion method.
    • Note modified (2019-05-08) to call the new checkpointIfWALEnabled method prior to the copy, so that the database is checkpointed.
    • public class DatabaseHelper extends SQLiteOpenHelper {
      
          private  static final String DB_NAME = "dictionary.db";
          private static final int DB_VERSION = 1;
          //private String DB_PATH = null; //<<<<<<<<<< NOT NEEDED
          public   static final String TABLE_DICTIONARY = "dictionary";
          public   static final String TABLE_BOOKMARK= "bookmark";
          public static final String COL_ID = "id";
          public static final String COL_WORD = "word";
          public static final String COL_DEFINITION = "definition";
          public Context mcontext;
          public SQLiteDatabase mDatabase;
      
          public DatabaseHelper(Context context) {
              super(context, DB_NAME, null, DB_VERSION);
              this.mcontext = context;
              Log.d("DBVERSION","The Database Version (as hard coded) is " + String.valueOf(DB_VERSION));
      
              int dbversion = DatabaseAssetHandler.getVersionFromDBFile(context,DB_NAME);
              Log.d("DBVERSION","The Database Version (as per the database file) is " + String.valueOf(dbversion));
      
              // Copy the Database if no database exists
              if (!DatabaseAssetHandler.checkDataBase(context,DB_NAME)) {
                  DatabaseAssetHandler.copyDataBase(context,DB_NAME,true,DB_VERSION);
              } else {
                  if (DB_VERSION > dbversion && DatabaseAssetHandler.checkDataBase(context, DB_NAME)) {
                      DatabaseAssetHandler.copyDataBase(context, DB_NAME, true,DB_VERSION);
                      DatabaseAssetHandler.clearForceBackups(context, DB_NAME); // Clear the backups
                  }
              }
              mDatabase = this.getWritableDatabase(); //<<<<<<<<<<<<<
          }
      
          @Override
          public void onCreate(SQLiteDatabase db) {
          }
      
          @Override
          public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
          }
      
          public void openDatabase() throws SQLException {
              mDatabase = this.getWritableDatabase();
          }
      
          @Override
          public synchronized void close() {
              if (mDatabase != null)
                  mDatabase.close();
              super.close();
          }
      }
      

      -注释已修改(2019-05-08)以将版本号传递给copyDatabase方法.

      - Note modified (2019-05-08) to pass the version number to the copyDatabase method.

      public class MainActivity extends AppCompatActivity {
      
          DatabaseHelper mDBHlpr;
      
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
              mDBHlpr = new DatabaseHelper(this);
              Cursor csr = mDBHlpr.getWritableDatabase().query(
                      DatabaseHelper.TABLE_DICTIONARY,
                      null,null,null,null,null,null
              );
              DatabaseUtils.dumpCursor(csr);
              csr.close();
          }
      }
      

      结果

      首先,使用外部工具在字典表中创建了两行的数据库,并将其复制到资产文件夹中.

      Results

      First a database was created using an external tool with 2 rows in the dictionary table and copied into the assets folder.

      第一次运行,从assets文件夹复制数据库,并在日志中包含:-

      The first run, copies the database from the assets folder and results in the log containing :-

      04-17 19:24:54.249 3233-3233/m.example.so55711282dictionary D/DBVERSION: The Database Version (as hard coded) is 1
      04-17 19:24:54.249 3233-3233/m.example.so55711282dictionary D/DBVERSION: The Database Version (as per the database file) is -666666666
      04-17 19:24:54.249 3233-3233/m.example.so55711282dictionary D/DBPATH: DB Path is /data/data/m.example.so55711282dictionary/databases/dictionary.db
      04-17 19:24:54.250 3233-3233/m.example.so55711282dictionary D/COPYDATABASE: Initiated Copy of the database file dictionary.db from the assets folder.
      04-17 19:24:54.251 3233-3233/m.example.so55711282dictionary D/COPYDATABASE: Asset file dictionary.db found so attmepting to copy to /data/data/m.example.so55711282dictionary/databases/dictionary.db
      04-17 19:24:54.251 3233-3233/m.example.so55711282dictionary D/COPYDATABASE: Attempting copy of block 1 which has 4096 bytes.
      04-17 19:24:54.251 3233-3233/m.example.so55711282dictionary D/COPYDATABASE: Attempting copy of block 2 which has 4096 bytes.
      04-17 19:24:54.251 3233-3233/m.example.so55711282dictionary D/COPYDATABASE: Attempting copy of block 3 which has 4096 bytes.
      04-17 19:24:54.251 3233-3233/m.example.so55711282dictionary D/COPYDATABASE: Finished copying Database dictionary.db from the assets folder, to  /data/data/m.example.so55711282dictionary/databases/dictionary.db12288were copied, in 3 blocks of size 4096.
      04-17 19:24:54.251 3233-3233/m.example.so55711282dictionary D/COPYDATABASE: All Streams have been flushed and closed.
      04-17 19:24:54.273 3233-3233/m.example.so55711282dictionary I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@22ee92e7
      04-17 19:24:54.273 3233-3233/m.example.so55711282dictionary I/System.out: 0 {
      04-17 19:24:54.273 3233-3233/m.example.so55711282dictionary I/System.out:    id=1
      04-17 19:24:54.273 3233-3233/m.example.so55711282dictionary I/System.out:    word=Apple
      04-17 19:24:54.273 3233-3233/m.example.so55711282dictionary I/System.out:    definition=Thing that drops from an Apple Tree.
      04-17 19:24:54.273 3233-3233/m.example.so55711282dictionary I/System.out: }
      04-17 19:24:54.273 3233-3233/m.example.so55711282dictionary I/System.out: 1 {
      04-17 19:24:54.273 3233-3233/m.example.so55711282dictionary I/System.out:    id=2
      04-17 19:24:54.273 3233-3233/m.example.so55711282dictionary I/System.out:    word=Bucket
      04-17 19:24:54.273 3233-3233/m.example.so55711282dictionary I/System.out:    definition=Hand held container with carrying hanlde.
      04-17 19:24:54.273 3233-3233/m.example.so55711282dictionary I/System.out: }
      04-17 19:24:54.273 3233-3233/m.example.so55711282dictionary I/System.out: <<<<<
      

      即已从资产文件夹复制数据库,并转储了预期的行.

      运行2

      在不进行任何更改的情况下,重新运行了该应用程序(以测试它不会重新复制数据库):- 这次logcat包含:-

      i.e. The database has been copied from the assets folder and the expected rows have been dumped.

      Run 2

      Without making any changes the App was rerun (to test that it doesn't recopy the database) :- This time the logcat contains :-

      04-17 19:30:57.444 3343-3343/? D/DBVERSION: The Database Version (as hard coded) is 1
      04-17 19:30:57.445 3343-3343/? D/DBVERSION: The Database Version (as per the database file) is 1
      04-17 19:30:57.445 3343-3343/? D/DBPATH: DB Path is /data/data/m.example.so55711282dictionary/databases/dictionary.db
      04-17 19:30:57.449 3343-3343/? I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@22ee92e7
      04-17 19:30:57.449 3343-3343/? I/System.out: 0 {
      04-17 19:30:57.449 3343-3343/? I/System.out:    id=1
      04-17 19:30:57.449 3343-3343/? I/System.out:    word=Apple
      04-17 19:30:57.450 3343-3343/? I/System.out:    definition=Thing that drops from an Apple Tree.
      04-17 19:30:57.450 3343-3343/? I/System.out: }
      04-17 19:30:57.450 3343-3343/? I/System.out: 1 {
      04-17 19:30:57.450 3343-3343/? I/System.out:    id=2
      04-17 19:30:57.450 3343-3343/? I/System.out:    word=Bucket
      04-17 19:30:57.450 3343-3343/? I/System.out:    definition=Hand held container with carrying hanlde.
      04-17 19:30:57.450 3343-3343/? I/System.out: }
      04-17 19:30:57.450 3343-3343/? I/System.out: <<<<<
      

      即该数据库(如果存在)尚未被复制.

      运行3.

      通过使用外部工具添加另外两行来修改数据库,然后将其复制到资产文件夹中,以替换较旧的数据库文件,并且DB_VERSION更改为2.

      i.e. the database, as it exists, has not been copied.

      Run 3.

      The database has been modified by adding another two rows using an external tool and then copied into the assets folder replacing the older database file and DB_VERSION is changed to 2.

      日志包含:-

      04-17 19:35:16.661 3459-3459/m.example.so55711282dictionary D/DBVERSION: The Database Version (as hard coded) is 2
      04-17 19:35:16.661 3459-3459/m.example.so55711282dictionary D/DBVERSION: The Database Version (as per the database file) is 1
      04-17 19:35:16.661 3459-3459/m.example.so55711282dictionary D/DBPATH: DB Path is /data/data/m.example.so55711282dictionary/databases/dictionary.db
      04-17 19:35:16.661 3459-3459/m.example.so55711282dictionary D/DBPATH: DB Path is /data/data/m.example.so55711282dictionary/databases/dictionary.db
      04-17 19:35:16.661 3459-3459/m.example.so55711282dictionary D/COPYDATABASE: Initiated Copy of the database file dictionary.db from the assets folder.
      04-17 19:35:16.661 3459-3459/m.example.so55711282dictionary D/COPYDATABASE: Asset file dictionary.db found so attmepting to copy to /data/data/m.example.so55711282dictionary/databases/dictionary.db
      04-17 19:35:16.662 3459-3459/m.example.so55711282dictionary D/COPYDATABASE: Attempting copy of block 1 which has 4096 bytes.
      04-17 19:35:16.662 3459-3459/m.example.so55711282dictionary D/COPYDATABASE: Attempting copy of block 2 which has 4096 bytes.
      04-17 19:35:16.662 3459-3459/m.example.so55711282dictionary D/COPYDATABASE: Attempting copy of block 3 which has 4096 bytes.
      04-17 19:35:16.662 3459-3459/m.example.so55711282dictionary D/COPYDATABASE: Finished copying Database dictionary.db from the assets folder, to  /data/data/m.example.so55711282dictionary/databases/dictionary.db12288were copied, in 3 blocks of size 4096.
      04-17 19:35:16.662 3459-3459/m.example.so55711282dictionary D/COPYDATABASE: All Streams have been flushed and closed.
      04-17 19:35:16.689 3459-3459/m.example.so55711282dictionary I/System.out: >>>>> Dumping cursor android.database.sqlite.SQLiteCursor@16011e94
      04-17 19:35:16.689 3459-3459/m.example.so55711282dictionary I/System.out: 0 {
      04-17 19:35:16.689 3459-3459/m.example.so55711282dictionary I/System.out:    id=1
      04-17 19:35:16.689 3459-3459/m.example.so55711282dictionary I/System.out:    word=Apple
      04-17 19:35:16.689 3459-3459/m.example.so55711282dictionary I/System.out:    definition=Thing that drops from an Apple Tree.
      04-17 19:35:16.689 3459-3459/m.example.so55711282dictionary I/System.out: }
      04-17 19:35:16.689 3459-3459/m.example.so55711282dictionary I/System.out: 1 {
      04-17 19:35:16.689 3459-3459/m.example.so55711282dictionary I/System.out:    id=2
      04-17 19:35:16.689 3459-3459/m.example.so55711282dictionary I/System.out:    word=Bucket
      04-17 19:35:16.689 3459-3459/m.example.so55711282dictionary I/System.out:    definition=Hand held container with carrying hanlde.
      04-17 19:35:16.689 3459-3459/m.example.so55711282dictionary I/System.out: }
      04-17 19:35:16.689 3459-3459/m.example.so55711282dictionary I/System.out: 2 {
      04-17 19:35:16.690 3459-3459/m.example.so55711282dictionary I/System.out:    id=3
      04-17 19:35:16.690 3459-3459/m.example.so55711282dictionary I/System.out:    word=Yelllow
      04-17 19:35:16.690 3459-3459/m.example.so55711282dictionary I/System.out:    definition=A colour.
      04-17 19:35:16.690 3459-3459/m.example.so55711282dictionary I/System.out: }
      04-17 19:35:16.690 3459-3459/m.example.so55711282dictionary I/System.out: 3 {
      04-17 19:35:16.690 3459-3459/m.example.so55711282dictionary I/System.out:    id=4
      04-17 19:35:16.690 3459-3459/m.example.so55711282dictionary I/System.out:    word=Zebra
      04-17 19:35:16.690 3459-3459/m.example.so55711282dictionary I/System.out:    definition=A balck and white, horse-like animal.
      04-17 19:35:16.690 3459-3459/m.example.so55711282dictionary I/System.out: }
      04-17 19:35:16.690 3459-3459/m.example.so55711282dictionary I/System.out: <<<<<
      

      运行4.

      该应用已重新运行(不会重新复制数据库并转储4行)

      Run 4.

      The App is rerun (doesn't recopy the database and dumps the 4 rows)

      该应用已卸载并重新运行(当数据库版本为2时反映了该应用的新安装(例如,从playstore下载/安装该应用)):-

      The App is uninstalled and rerun (reflecting a new installation of the App when the Database version is at 2 (e.g. new download/install of the App from playstore)) :-

      复制数据库(具有4行的版本),并转储4行.

      The Database (version with 4 rows) is copied and the 4 rows are dumped.

      • 请注意,其中包括了 数据库版本(根据数据库文件)为-666666666 的消息.当没有要替换的数据库时会显示此信息(可以轻松更改数量以适合数据库).

      这篇关于关于升级方法没有在Android sqlite中被调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆