2012-06-08 70 views
5

复制我使用本教程: Tutorial Custom database升级SQLite数据库,我是从资产的文件夹(安卓)

我从资产文件夹复制数据库,并将其复制到我的设备(或模拟器)。一切都是正确的。我从DDMS的角度看到我的数据库。但我想ASLO升级我的数据库有时,所以我所做的:

super(context, DB_NAME, null, 2); //changed version from 1 to 2 

和修改onUpgrade方法:

@Override 
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
    if(newVersion > oldVersion){ 
     this.myContext.deleteDatabase(DB_NAME); 
     try { 
      this.copyDataBase(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

但运行后我还有我的设备上旧版本的数据库。我如何删除旧版本的数据库并复制新的。 DB_NAME是我的数据库名称(带有格式,但不包含路径),copyDataBase()是将数据库复制到设备(以及它工作)的方法。

我贴我的所有代码:

public class DataBaseHelper extends SQLiteOpenHelper{ 

    private static String DB_PATH = "/data/data/sitcom.quiz/databases/"; 

    private static String DB_NAME = "sitcoms.sqlite"; 

    private SQLiteDatabase myDataBase; 

    private final Context myContext; 

    public DataBaseHelper(Context context) { 

     super(context, DB_NAME, null, 4); 
     this.myContext = context; 
    } 

    public void createDataBase() throws IOException{ 

     boolean dbExist = checkDataBase(); 

     if(dbExist){ 
      //do nothing - database already exist 
     }else{ 

      this.getReadableDatabase(); 

      try { 

       copyDataBase(); 

      } catch (IOException e) { 

       throw new Error("Error copying database"); 

      } 
     } 

    } 

    private boolean checkDataBase(){ 

     SQLiteDatabase checkDB = null; 

     try{ 
      String myPath = DB_PATH + DB_NAME; 
      checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY); 

     }catch(SQLiteException e){ 
      //database does't exist yet. 
     } 

     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[1024]; 
     int length; 
     while ((length = myInput.read(buffer))>0){ 
      myOutput.write(buffer, 0, length); 
     } 

     //Close the streams 
     myOutput.flush(); 
     myOutput.close(); 
     myInput.close(); 

    } 

    public void openDataBase() throws SQLException{ 

     //Open the database 
     String myPath = DB_PATH + DB_NAME; 
     myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY); 

    } 

    @Override 
    public synchronized void close() { 

      if(myDataBase != null) 
       myDataBase.close(); 

      super.close(); 

    } 

    @Override 
    public void onCreate(SQLiteDatabase db) { 

    } 

    @Override 
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
     Log.d("adas", "dasd"); 

     if(newVersion > oldVersion){ 
      String myPath = DB_PATH + DB_NAME; 
      this.myContext.deleteDatabase(myPath); 
      try { 
       this.copyDataBase(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 


} 

和我的活动:

DataBaseHelper myDbHelper = new DataBaseHelper(this); 
     myDbHelper = new DataBaseHelper(this); 

     try { 
      myDbHelper.createDataBase(); 
     } catch (IOException ioe) { 
      throw new Error("Unable to create database"); 
     } 
     try { 
      myDbHelper.openDataBase(); 
     }catch(SQLException sqle){ 
      throw sqle; 
     } 

感谢您是否可以给我一个理由或只能暗示为什么别工作。

回答

5

当函数onUpgrade()被调用时,android已经打开了数据库。我不认为有可能在这个时候删除它。检查日志以获取更多信息。如果你想这样做,你需要将删除和复制代码移动到数据库尚未打开的位置。

+0

是的,你是对的。我做了什么 ?我使用共享首选项来签署新版本的数据库,并在使用此对象之前删除数据库。谢谢。 – kolek

+2

@ kolek:你能与大家分享解决方案吗?我也需要类似的东西。 –

+0

为什么不分享解决方案,Kolek?请,很多人需要它。 –

2

试试这个代码...我认为它会解决你的问题。

public void onUpgrade(SQLiteDatabase database, int oldVersion, 
     int newVersion) { 
    Log.w(DatabaseHelper.class.getName(), 
      "Upgrading database from version " + oldVersion + " to " 
        + newVersion + ", which will destroy all old data"); 
    database.execSQL("DROP TABLE IF EXISTS " + DATABASE_NAME); 
    onCreate(database); 
} 
0

您可以在升级数据库之前删除旧的Db。

if(dbExist){ 
       Log.v("com.db","db exists"); 
       myContext.deleteDatabase(DB_NAME);`enter code here` 
       //openDataBase(); 
       //do nothing - database already exist 
      }else{ 
       Log.v("com.db","dbnot exists"); 
       //By calling this method and empty database will be created into the default system path 
        //of your application so we are gonna be able to overwrite that database with our database. 
       this.getReadableDatabase(); 
} 
0

只是一个加法:

中的CreateDatabase

()有下面的检查;

this.getReadableDatabase();

这将检查是否已经存在具有提供名称的数据库,是否创建空数据库以便可以使用assets文件夹中的数据库覆盖它。在较新的设备上,它可以完美地工作,但有些设备无法正常工作。主要是旧设备。我不知道究竟是什么原因,但似乎getReadableDatabase()函数不仅获取数据库,而且还打开它。如果您然后将资产文件夹中的数据库复制到它上面,它仍然具有指向空数据库的指针,并且您将得到表不存在的错误。

因此,为了使所有设备上工作,你应该把它修改为以下行:

SQLiteDatabase db = this.getReadableDatabase(); 
if (db.isOpen()){ 
    db.close(); 
} 

即使数据库在检查开,此后它被关上,它不会给你任何更多的麻烦。

1

当从资产复制数据库时,缺省情况下版本为0. 在从资产复制数据库的方法中,使用方法setVersion(int version)为数据库对象设置其版本。 如果数据库存在,请通过数据库对象上的方法getVersion()检查其版本。现在自己处理onUpgrade即如果db evrsion已经更新了noe,然后升级数据库,然后setVersion(int new dbVersion)

0

主要思想是当你创建新的数据库时,你应该使用SharedPreferences来存储你的数据库版本。
之后,当您创建数据库时,必须检查是否有数据库新版本,那么你删除旧的数据库,并创建了我新的一个
此代码工作

private static class DatabaseHelper extends SQLiteOpenHelper { 

     private static final String DATABASE_NAME = "database.name"; 
     private static final int DATABASE_VERSION = 1; 
     private static final String KEY_DB_VER = "database_version"; 
     private final Context mContext; 

     public DatabaseHelper(Context context) { 
      super(context, DATABASE_NAME, null, DATABASE_VERSION); 
      mContext = context; 
      initialize(); 
     } 

     /** 
     * Initializes database. Creates database if doesn't exist. 
     */ 
     private void initialize() { 
      if (databaseExists()) { 
       SharedPreferences prefs = PreferenceManager 
         .getDefaultSharedPreferences(mContext); 
       int dbVersion = prefs.getInt(KEY_DB_VER, 1); 
       // 
       if (DATABASE_VERSION != dbVersion) { 
        File dbFile = mContext.getDatabasePath(DATABASE_NAME); 
        // delete the old databse 
        if (!dbFile.delete()) { 
         Log.w(TAG, "Unable to update database"); 
        } 
       } 
      } 
      // create database if needed 
      if (!databaseExists()) { 
       createDatabase(); 
      } 
     } 

     /** 
     * Returns true if database file exists, false otherwise. 
     * @return 
     */ 
     private boolean databaseExists() { 
      File dbFile = mContext.getDatabasePath(DATABASE_NAME); 
      return dbFile.exists(); 
     } 

     public void createDataBase() throws IOException { 
      // If database not exists copy it from the assets 
      boolean mDataBaseExist = databaseExists(); 

      if (!mDataBaseExist) { 
       this.getReadableDatabase(); 
       this.close(); 
       try { 
        // Copy the database from assests 
        copyDataBase(); 

        //**save the database version by SharedPreferences** 

        SharedPreferences prefs = PreferenceManager 
          .getDefaultSharedPreferences(mContext); 
        SharedPreferences.Editor editor = prefs.edit(); 
        editor.putInt(KEY_DB_VER, DATABASE_VERSION); 
        editor.commit(); 

        Log.e(TAG, "createDatabase database created"); 

       } catch (IOException mIOException) { 
        throw new Error("ErrorCopyingDataBase"); 
       } 
      } 
     } 

     // Copy the database from assets 
     private void copyDataBase() throws IOException { 
      Log.i("TAG", "copy database"); 
      InputStream mInput = mContext.getAssets().open(DB_NAME); 
      String outFileName = DB_PATH + DB_NAME; 
      OutputStream mOutput = new FileOutputStream(outFileName); 
      byte[] mBuffer = new byte[1024]; 
      int mLength; 
      while ((mLength = mInput.read(mBuffer)) > 0) { 
       mOutput.write(mBuffer, 0, mLength); 
      } 
      mOutput.flush(); 
      mOutput.close(); 
      mInput.close(); 
     } 

     @Override 
     public void onCreate(SQLiteDatabase db) { 
     } 

     @Override 
     public void onUpgrade(SQLiteDatabase db, int oldVersion, 
       int newVersion) { 
     } 
    } 
相关问题