2011-08-24 10 views
7

Estoy usando este DataBaseHelper.class y estoy atascado en el método onUpgrade(). No sé cómo averiguar cuál es el número de versión de la base de datos. Podría establecer la versión en 1, la primera vez que la publique y cuando publique una actualización, simplemente podría establecer la versión en 2 (myDataBase.setVersion(2);). Pero solo será 2 siempre que la aplicación se esté ejecutando. La próxima vez que se inicie, es 1 de nuevo. Lo mismo ocurre con private static int DATABASE_VERSION. Estaba pensando en almacenar el número de versión en una mesa extra, pero esta no parece ser la mejor práctica en mi opinión.onUpgrade database - oldVersion - newVersion

Entonces, ¿cómo se asegura de que el número de versión haya aumentado después de una actualización y que lo mantiene (el valor que fue asignado a private static int DATABASE_VERSION o myDataBase.getVersion();)?

El DataBaseHelper clase:

public class DataBaseHelper extends SQLiteOpenHelper { 

    //The Android's default system path of your application database. 
    private static String DB_PATH = "/data/data/com.mydatabase.db/databases/"; 

    private static String DB_NAME = "database.sl3"; 

    private SQLiteDatabase myDataBase; 

    private final Context myContext; 


    // Do you need this? 
    private static int DATABASE_VERSION = 2; 
    // or is this correct: 
    // private static int DATABASE_VERSION = myDataBase.getVersion(); 


    /** 
    * Constructor 
    * Takes and keeps a reference of the passed context in order to access to 
    * the application assets and resources. 
    * 
    * @param context 
    */ 
    public DataBaseHelper(Context context) { 

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

    /** 
    * Creates an empty database on the system and rewrites it with your own 
    * database. 
    * */ 
    public void 
     createDataBase() throws IOException { 
     boolean dbExist = checkDataBase(); 

     if (dbExist) { 


     } 
     else { 

      //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.getWritableDatabase(); 


      try { 

       copyDataBase(); 

      } catch (IOException e) { 

       throw new Error("Error copying database"); 

      } 
     } 

    } 

    /** 
    * Check if the database already exist to avoid re-copying the file each 
    * time you open the application. 
    * 
    * @return true if it exists, false if it doesn't 
    */ 
    private boolean 
     checkDataBase() { 

     SQLiteDatabase checkDB = null; 

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

     } catch (SQLiteException e) { 

      //database does't exist yet. 

     } 

     if (checkDB != null) { 

      checkDB.close(); 

     } 
     return checkDB != null ? true : false; 
    } 

    /** 
    * Copies your database from your local assets-folder to the just created 
    * empty database in the 
    * system folder, from where it can be accessed and handled. 
    * This is done by transfering bytestream. 
    * */ 
    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_READWRITE); 



     // Which parameters do I have to pass? 
     onUpgrade(myDataBase, DATABASE_VERSION, 2); 
    } 

    @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 ("onUpgrade first log", Integer.toString(myDataBase.getVersion())); 




    if (oldVersion == 1) { 

     // do something 


     // And then do this!? 
     DATABASE_VERSION = 2; 
     // or do this 
     myDataBase.setVersion(2); 
     Log.d ("onUpgrade sedond log", Integer.toString(myDataBase.getVersion())); 

    } 

    else { 
     Log.d("onUpgrade", "else-clause: Already upgraded!"); 
    } 



} 

Respuesta

11
// Do you need this? 
private static int DATABASE_VERSION = 2; 

Sí, usted necesita esto. (Mejor aún, también sea final)

Esto le dice al asistente de la base de datos cuál es la última versión del esquema de la base de datos. Esto debe corregirse en el código de su aplicación y aumentarse cada vez que modifique el esquema.

Cuando se inicia la aplicación, el ayudante verifica en tiempo de ejecución que la idea de su código de la última versión es la misma que la que estaba activa cuando se creó o actualizó la base de datos por última vez. (Esto es para lo que es db.getVersion()). Si los números no coinciden, entonces el auxiliar sabe que la base de datos almacenada está desactualizada con respecto al código de su aplicación, por lo que ejecuta la rutina de actualización.

Parece que no está creando la base de datos desde el principio, sino que está importando una base de datos existente de sus activos. Cuando realiza esta importación inicial, este es el momento para asegurarse de que la versión almacenada coincida con la versión de su código; ya sea que lo aplique directamente al archivo de base de datos en sus activos o, si está seguro de que el archivo de base de datos en sus activos coincide con el código, llame al setVersion(DATABASE_VERSION).

En cualquier caso, no debería tratar de modificar los números de versión en la rutina onUpgrade(). Esto solo se llama si las versiones no coinciden, y todo lo que se supone que debe hacer aquí es hacer los cambios necesarios para actualizar la base de datos. El ayudante administrará el almacenamiento del nuevo número de versión una vez que se complete la actualización.

+0

Hola Graham Borland! Tiene razón, importo una base de datos existente de la carpeta de activos y creo que esto es lo que necesito _aplicarlo directamente al archivo de base de datos en sus assets_! ¿Pero cómo hago esto? – BenjaminButton

+0

Con _it_ quise decir el número de versión. – BenjaminButton

+1

¡Lo tengo funcionando! En la clase createDataBase faltaba una línea: 'public void createDataBase() arroja IOException {boolean dbExist = checkDataBase(); if (dbExist) {/ * Esta línea: */this.getWritableDatabase();} ... ' Además se invoca onUpgrade() cuando se crea un nuevo objeto de la clase DataBaseHelper ** pero ** solo si la base de datos los números de versión no coinciden. Por lo tanto, esto significa que no es necesario llamar a Actualizaciones "por su cuenta". Si publica una actualización de su base de datos, simplemente incremente la versión nr en uno y aplique los cambios en el método onUpgrade(). Espero que ayude a cualquiera! – BenjaminButton

1

Agregando alguna información a la respuesta de Graham Borland. Explicaré con el escenario de la aplicación en la que su base de datos está en la carpeta de activos y la copiará en su carpeta de paquetes si aún no está presente allí. Ahora, si desea actualizar su aplicación con la base de datos actualizada. es necesario establecer

private final static int DB_VERSION=2;   // Database Version 

en su clase de base de datos de ayuda.

(Cualquier entero que debería ser más que la versión inicial dB, lo que configura initialy en esta clase)

Después de que se necesita añadir un código de anulación ONUPGRADE() En este scenarion I overrite edad db con el último.Usted puede cambiar su código como su gusto

@Override 
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
     // TODO Auto-generated method stub 
      CopyNewDatabaseFromAsset(); 
    } 

Si necesita ninguna explicación por favor, puesto en el comentario :)