java - sqlitedatabase - ¿El método onUpgrade alguna vez se llama?
sqliteopenhelper example (6)
Al SqliteOpenHelper
código fuente de SqliteOpenHelper
, podemos saber que se onCreate()
, onUpgrade()
y onDowngrade
en el getWritableDatabase()
o getReadableDatabase()
.
public SQLiteDatabase getWritableDatabase() {
synchronized (this) {
return getDatabaseLocked(true);
}
}
public SQLiteDatabase getReadableDatabase() {
synchronized (this) {
return getDatabaseLocked(false);
}
}
private SQLiteDatabase getDatabaseLocked(boolean writable) {
if (mDatabase != null) {
if (!mDatabase.isOpen()) {
// Darn! The user closed the database by calling mDatabase.close().
mDatabase = null;
} else if (!writable || !mDatabase.isReadOnly()) {
// The database is already open for business.
return mDatabase;
}
}
. . . . . .
final int version = db.getVersion();
if (version != mNewVersion) {
if (db.isReadOnly()) {
throw new SQLiteException("Can''t upgrade read-only database from version " +
db.getVersion() + " to " + mNewVersion + ": " + mName);
}
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);
if (db.isReadOnly()) {
Log.w(TAG, "Opened " + mName + " in read-only mode");
}
mDatabase = db;
return db;
} finally {
mIsInitializing = false;
if (db != null && db != mDatabase) {
db.close();
}
}
}
¿ onUpgrade
SQLiteOpenHelper
alguna vez el método onUpgrade
de SQLiteOpenHelper
? Si es así, ¿cuándo se llama y por qué? Si los desarrolladores no lo llaman, ¿por qué está ahí? ¿Qué sucede realmente con esa función? He visto ejemplos en los que se eliminan todas las tablas, pero luego un comentario dice que dejar caer todas las tablas no es lo que debes hacer. ¿Alguna sugerencia?
Al revisar todas las publicaciones y ejecutar el código de depuración, aún no estaba claro para mí cuando veía que se llamaba a OnUpgrade. Estaba empezando a pensar que Android tenía un defecto grave ...
La información en esta página me llevó a mi resolución final. ¡Muchas gracias a todos los colaboradores!
Esto lo resolvió para mí ...
public class DatabaseHelper extends SQLiteOpenHelper {
public static String TAG = DatabaseHelper.class.getName();
private static final int DATABASE_VERSION = 42;
private static final String DATABASE_NAME = "app_database";
private static final String OLD_TABLE = "old_and_useless";
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion ) {
if( newVersion > oldVersion) {
Log.d( TAG, "cool! you noticed." );
db.execSQL( "DROP TABLE IF EXISTS " + OLD_TABLE );
// other calls like onCreate if necessary
} else {
Log.d( TAG, "Hey! didn''t you see me?" );
}
}
public void checkDatabaseVersion() {
SQLiteDatabase db = this.getWritableDatabase();
// if the DATABASE_VERSION is newer
// onUpgrade is called before this is reached
}
// other code removed for readability...
}
Es cierto que getWritableDatabase () y getReadableDatabase () da como resultado la llamada onUpgrade. No revisé otros métodos ya que estos se ajustan a mis necesidades.
Sigue leyendo, el golpeador viene ...
Este código en mi Actividad inicial me iluminó cuando finalmente me di cuenta de que la versión de db se estaba actualizando durante mi depuración ... ugh!
DatabaseHelper dbHelper = new DatabaseHelper( this );
dbHelper.checkDatabaseVersion();
NOTA: al llamar al constructor DatabaseHelper se actualiza la versión db
Después de la llamada al constructor, el db se etiquetó con la nueva versión. Elimina la aplicación antes de una llamada a getWritableDatabase () o getReadableDatabase () y estás en la nueva versión. A partir de entonces, las nuevas ejecuciones nunca llaman al método onUpgrade hasta que DATABASE_VERSION se incremente nuevamente. ( suspiro! Ahora parece ridículamente obvio :)
Mi sugerencia es agregar algún tipo de "checkDatabaseVersion ()" a las primeras etapas de su aplicación. Alternativamente, si crea un objeto SQLiteOpenHelper, asegúrese de llamar a uno de los métodos (getWritableDatabase (), getReadableDatabase (), etc.) antes de que su aplicación fallezca.
¡Espero que esto le salve a alguien más el mismo rasguño en la cabeza! ...: p
En realidad se llama cuando llamas a getReadableDatabase
o getWritableDatabase
.
Bucear profundo:
SQLiteOpenHelper
el número de versión en el constructor de SQLiteOpenHelper
que está almacenado en una variable llamada mNewVersion
. Eso es. Nada sucede en este punto.
Cada vez que llame a getReadableDatabase o getWritableDatabase, llamará a un método llamado getDatabaseLocked
. Este método obtendrá el número de versión existente de la base de datos y lo comparará con mNewVersion
.
- Si la base de datos con el nombre de pila no existe, se llamará a
onCreate
- Si la nueva versión es mayor que la versión anterior, llamará a
onUpgrade
. - Si la nueva versión es más baja que la versión existente, se lanzará una excepción.
- Si son iguales, continuará y abrirá la base de datos.
¿Qué debo escribir en onCreate y onUpgrade?
onCreate
debe contener el código que crea un esquema por primera vez.
Puede dejar onUpgrade
vacío por primera vez ya que no se llamará la primera vez. Cuando desee cambiar la estructura de la tabla en una etapa posterior, ese código debería ir aquí.
SQLiteOpenHelper.java (código fuente)
public SQLiteDatabase getWritableDatabase() {
synchronized (this) {
return getDatabaseLocked(true);
}
}
public SQLiteDatabase getReadableDatabase() {
synchronized (this) {
return getDatabaseLocked(false);
}
}
private SQLiteDatabase getDatabaseLocked(boolean writable) {
.
.
final int version = db.getVersion();
if (version != mNewVersion) {
if (db.isReadOnly()) {
throw new SQLiteException("Can''t upgrade read-only database from version " +
db.getVersion() + " to " + mNewVersion + ": " + mName);
}
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);
}
Para aquellos de ustedes que deseen saber el momento exacto en que se llama a onUpgrade()
, es durante una llamada a getReadableDatabase()
o getWriteableDatabase()
.
Para aquellos que no están seguros de cómo se activa, la respuesta es: se activa cuando se actualiza la versión de la base de datos provista al constructor de SqLiteOpenHelper
. Aquí hay un ejemplo
public class dbSchemaHelper extends SQLiteOpenHelper {
private String sql;
private final String D_TAG = "FundExpense";
//update this to get onUpgrade() method of sqliteopenhelper class called
static final int DB_VERSION = 2;
static final String DB_NAME = "fundExpenseManager";
public dbSchemaHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
// TODO Auto-generated constructor stub
}
ahora para ... onUpgrade ()
@Override
public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) {
sql = "ALTER TABLE " + fundExpenseSchema.Expense.TABLE_NAME + " ADD COLUMN " + fundExpenseSchema.Expense.FUNDID + " INTEGER";
arg0.execSQL(sql);
}
Se llama cuando construye un SQLiteOpenHelper con una versión más nueva que la versión de la base de datos abierta. Qué hacer depende de los cambios en la base de datos que se realizan entre la versión anterior y la nueva. El único caso en el que no descarta una tabla modificada es cuando el cambio marca más que una columna adicional. Luego puede usar la instrucción ALTER TABLE para agregar la nueva columna a la firma de la tabla.
si está utilizando el SQLiteOpenHelper, se llamará a la actualización cuando se cambie la versión de DB. Hay un requisito adicional para que esto funcione. El nombre db debe permanecer igual.
Old Version:
dbName = "mydb.db"
dbVersion = 1
New Version:
dbName = "mydb.db"
dbVersion = 2
en el onCreate del proveedor de contenido, usted crea una instancia del SQLiteOpenHelper que toma estos parámetros. Su implementación SQLiteOpenHelper se vería así:
public static final class MySQLiteOpenHelper extends SQLiteOpenHelper {
public MySQLiteOpenHelper(Context context, int dbVersion, String dbName) {
super(context, dbName, null, dbVersion);
}
@Override
public void onCreate(SQLiteDatabase db) {
//Code to create your db here
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// Code to upgrade your db here
}
}