¿Se llama 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?¿Alguna vez se llama al método de actualización?
Respuesta
Se llama cuando se 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 SQLiteOpenHelper se llamará a la actualización siempre que cambie la versión de la base de datos. Existe 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 se crea una instancia de la SQLiteOpenHelper que toma estos parametros. Su aplicació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
}
}
¡Gracias! Ahora finalmente entendí cómo usar onUpgrade :-) – marlar
@ dev.serghini ¿Dónde encontraste información de que cambiar el nombre de la versión de DB solo activa 'onUpgrade'? Necesito confirmación oficial para esto y no puedo encontrarlo en los documentos oficiales de Java de este método. – sandalone
entonces surge una nueva pregunta: ¿Cuándo se cambia la "dbVersion"? ¿el desarrollador controla eso? como la "aplicaciónVersión" de la aplicación? – sports
Para aquellos de ustedes que le gustaría saber el momento exacto en que se llama a onUpgrade()
, es durante una llamada a cualquiera de 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 proporcionada al constructor de SqLiteOpenHelper
. Aquí está 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 a ... 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);
}
En realidad, se llama a OnUpgrade solo si llama a getWriteableDatabase(). –
gracias por esta explicación –
@DoctororDrive - también llamado en 'getReadableDatabase()'; ambos llaman 'getDatabaseLocked (boolean writeable)' – CJBS
de revisar todos los mensajes y la ejecución de código de depuración que todavía no estaba claro para mí cuando veía ONUPGRADE recibiendo llamadas. 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 resolvió por 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 lugar a la llamada ONUPGRADE. No revisé otros métodos ya que estos se ajustan a mis necesidades.
lectura Keep, el truco está llegando ...
Este código en mi actividad inicial me iluminó cuando finalmente me di cuenta de que la versión del DB fue la actualización de depuración durante mi ... uf!
DatabaseHelper dbHelper = new DatabaseHelper(this);
dbHelper.checkDatabaseVersion();
NOTA: llamando al constructor DatabaseHelper actualiza la versión db
Después de la llamada al constructor, el PP fue etiquetado 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 muera su aplicación.
Espero que esto le ahorre a alguien más el mismo rasguño en la cabeza !. ..: p
buscando en el código fuente SqliteOpenHelper
, podemos conocer onCreate()
, onUpgrade()
y onDowngrade
ser llamado en getWritableDatabase()
o getReadableDatabase()
método.
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();
}
}
}
Se llama en realidad se cuando llame getReadableDatabase
o getWritableDatabase
.
inmersión profunda:
se pasa el número de versión en el constructor de SQLiteOpenHelper
que se almacena 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 el mNewVersion
.
- Si no existe la base de datos con el nombre dado se llama
onCreate
- Si la nueva versión es mayor que la vieja versión se llamará
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);
}
- 1. ¿Cuándo se llama al método ConvertBack?
- 2. método IOS canAuthenticateAgainstProtectionSpace no se llama cada vez que
- 3. ¿Cuándo se llama al método IEnumerator.Reset()?
- 4. Afirmando que un método se llama exactamente una vez
- 5. Encuentra quién llama al método
- 6. ¿Cuándo se llama al método getView() de ListView?
- 7. ¿Por qué se llama al constructor una sola vez?
- 8. TabHost setCurrentTab sólo se llama al método alcrear para la actividad en la Tab vez
- 9. NSTimer no llama al método
- 10. método acelerómetro delegado no se llama
- 11. ¿Cuándo se llama al método onCreate() de la aplicación?
- 12. Mockito: cuando se llama al método A.a, ejecuta B.b
- 13. ¿Qué método de actividad se llama primero?
- 14. ¿Alguna vez se llama implícitamente a los establecedores de propiedades .Net?
- 15. RSpec. ¿Cómo verificar si se llama al método del objeto?
- 16. No se llama al método didReadData GCDAsynSocketDelegate. Usando GCDAsynSocket
- 17. define_method no usa variables hasta que se llama al método?
- 18. ¿Se desborda BigInteger alguna vez?
- 19. ¿Cómo se llama este método de almacenamiento?
- 20. Quiero utilizar un método que se llama una sola vez después de la implementación en Servidor
- 21. ¿Cómo puedo ejecutar algún código cuando se llama por primera vez al método de guardado de un modelo de Django?
- 22. trozo de código que se llama solo una vez: ¿merece un método propio?
- 23. ¿La superclase no llama al método reemplazado?
- 24. Android: FastScrolling SectionIndexer getSections() se llama una sola vez
- 25. Llamar a una macro cada vez que se llama a un método - Objetivo C
- 26. UIScrollView llama a layoutSubviews() cada vez que se desplaza
- 27. Cómo hacer que Mock devuelva una nueva lista cada vez que se llama al método usando Moq
- 28. Despedir a un evento cada vez que un nuevo método se llama
- 29. WebView: WebViewClient.onPageStarted método no se llama
- 30. HttpWebRequest.GetResponse() se cuelga la segunda vez que se llama
El cambio también podría estar agregando nuevas tablas, en cuyo caso puede que no se eliminen las tablas existentes. – CommonsWare
Pero, ¿cómo saber de antemano que va a modificar una tabla? O simplemente tiene que cambiar el método cada vez que publica una actualización. –
Usted sabe cuando está cambiando la base de datos y agrega otro caso en onUpgrade. Entonces, cuando el usuario actualiza la aplicación, SQLiteOpenHelper sabe que la base de datos existente está obsoleta y toma la acción correspondiente. Consulte una fuente de Android como referencia: http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;f=packages/SettingsProvider/src/com/android/providers /settings/DatabaseHelper.java – ognian