Tutorial CRUD Android + SQLite (VIII): Actualizar la base de datos SQLite

Posted by in Programación Android

Siguiendo con el Tutorial Android + SQLite en la entrada anterior vimos cómo incluir un menú contextual con las acciones de cada registro, en esta veremos cómo actualizar la versión de la base de datos SQLite.

Inluiremos una nueva columna para marcar registros como pasivos y los visualizaremos en el ListView con un color diferente. Para ello profundizaremos en los siguientes conceptos:

  • Método onUpgrade de la clase SQLiteOpenHelper.
  • Utilización del componente CheckBox.
  • Resaltar registros en ListView.

 

1: Método onUpgrade de la clase SQLiteOpenHelper

En la primera entrada del tutorial vimos la creación de la clase SQLiteOpenHelper controladora de la base de datos SQLite con el método onCrete. En esta entrada vamos a ver como realizar una actualización de la base de datos con el método onUpgrade.

Comenzamos modificando la versión definida en la clase HipotecaDbHelper.

...
...
public class HipotecaDbHelper extends SQLiteOpenHelper {

	private static int version = 3;
	private static String name = "HipotecaDb" ;
	private static CursorFactory factory = null;
	
	public HipotecaDbHelper(Context context)
	{
		super(context, name, factory, version);
	}
...
...

 

Durante la ejecución, al detectar el cambio de versión se llamará automáticamente al método onUpgrade de SQLiteOpenHelper indicando la versión anterior y la nueva. Por tanto, vamos a incluir cada una de las actualizaciones de la base de datos en un método privado que llamaremos desde onUpgrade. En el método upgrade_3 añadimos la nueva columna pasivo_sn a la base de datos SQLite.

...
...
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
    // Actualización a versión 2
    if (oldVersion < 2)
    {
        upgrade_2(db);
    }
    // Actualización a versión 3
    if (oldVersion < 3)
    {
        upgrade_3(db);
    }
}

private void upgrade_2(SQLiteDatabase db)
{
    //
    // Upgrade versión 2: definir algunos datos de ejemplo
    //
    db.execSQL( "UPDATE HIPOTECA SET hip_contacto = 'Julián Gómez Martínez'," +
                "					hip_email = 'jgmartinez@gmail.com'," +
                "					hip_observaciones = 'Tiene toda la documentación y está estudiando la solicitud. En breve llamará para informar de las condiciones'" +
                " WHERE _id = 1");

    Log.i(this.getClass().toString(), "Actualización versión 2 finalizada");
}

private void upgrade_3(SQLiteDatabase db)
{
    //
    // Upgrade versión 3: Incluir pasivo_sn
    //
    db.execSQL("ALTER TABLE HIPOTECA ADD hip_pasivo_sn   VARCHAR2(1) NOT NULL DEFAULT 'N'");

    Log.i(this.getClass().toString(), "Actualización versión 3 finalizada");
}
...
...

 

También llamaremos a estas actualizaciones desde el método onCreate ya que si la aplicación se instala directamente con la versión 3 de la base de datos nunca se realizarán estas actualizaciones al no haber sido instalada desde la versión 1.

...
...
@Override
public void onCreate(SQLiteDatabase db)
{
    Log.i(this.getClass().toString(), "Creando base de datos");
    
    db.execSQL( "CREATE TABLE HIPOTECA(" +
                " _id INTEGER PRIMARY KEY," +
                " hip_nombre TEXT NOT NULL, " +
                " hip_condiciones TEXT, " +
                " hip_contacto TEXT," +
                " hip_email TEXT," +
                " hip_telefono TEXT," +
                " hip_observaciones TEXT)" );
    
    db.execSQL( "CREATE UNIQUE INDEX hip_nombre ON HIPOTECA(hip_nombre ASC)" );
    
    Log.i(this.getClass().toString(), "Tabla HIPOTECA creada");
    
    /*
     * Insertamos datos iniciales
     */
    db.execSQL("INSERT INTO HIPOTECA(_id, hip_nombre) VALUES(1,'Santander')");
    db.execSQL("INSERT INTO HIPOTECA(_id, hip_nombre) VALUES(2,'BBVA')");
    db.execSQL("INSERT INTO HIPOTECA(_id, hip_nombre) VALUES(3,'La Caixa')");
    db.execSQL("INSERT INTO HIPOTECA(_id, hip_nombre) VALUES(4,'Cajamar')");
    db.execSQL("INSERT INTO HIPOTECA(_id, hip_nombre) VALUES(5,'Bankia')");
    db.execSQL("INSERT INTO HIPOTECA(_id, hip_nombre) VALUES(6,'Banco Sabadell')");
    db.execSQL("INSERT INTO HIPOTECA(_id, hip_nombre) VALUES(7,'Banco Popular')");
    
    Log.i(this.getClass().toString(), "Datos iniciales HIPOTECA insertados");
    
    Log.i(this.getClass().toString(), "Base de datos creada");

    // Aplicamos las sucesivas actualizaciones
    upgrade_2(db);
    upgrade_3(db);
}
...
...

 

2: HipotecaDbAdapter

Incluimos la nueva columna en la clase HipotecaDbAdapter utilizada para realizar las operaciones de la entidad HIPOTECA en la base de datos.

...
...
/**
 * Definimos constantes con el nombre de las columnas de la tabla
 */
public static final String C_COLUMNA_ID	= "_id";
public static final String C_COLUMNA_NOMBRE = "hip_nombre";
public static final String C_COLUMNA_CONDICIONES = "hip_condiciones";
public static final String C_COLUMNA_CONTACTO = "hip_contacto";
public static final String C_COLUMNA_EMAIL = "hip_email";
public static final String C_COLUMNA_TELEFONO = "hip_telefono";
public static final String C_COLUMNA_OBSERVACIONES = "hip_observaciones";
public static final String C_COLUMNA_PASIVO = "hip_pasivo_sn";
...
...
/**
 * Definimos lista de columnas de la tabla para utilizarla en las consultas a la base de datos
 */
private String[] columnas = new String[]{
        C_COLUMNA_ID,
        C_COLUMNA_NOMBRE,
        C_COLUMNA_CONDICIONES,
        C_COLUMNA_CONTACTO,
        C_COLUMNA_EMAIL,
        C_COLUMNA_TELEFONO,
        C_COLUMNA_OBSERVACIONES,
        C_COLUMNA_PASIVO} ;
...
...

 

3: Incluir CheckBox en formulario

Añadimos el CheckBox en el layout del formulario entre el campo observaciones y la botonera.

...
...
<CheckBox
    android:id="@+id/pasivo"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignLeft="@+id/observaciones"
    android:layout_below="@+id/observaciones"
    android:layout_marginTop="20dp"
    android:text="@string/label_pasivo" />


<LinearLayout
    android:id="@+id/botonera"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_below="@id/pasivo"
    android:gravity="center"
    android:layout_marginTop="20dp"
    android:orientation="horizontal" >

    <Button
        android:id="@+id/boton_cancelar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/boton_cancelar" />

    <Button
        android:id="@+id/boton_guardar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/boton_guardar" />

</LinearLayout>
...
...

android_sqlite_upgrade_1

Incluimos el nuevo campo en la clase HipotecaFormulario: en la definición y obtención de los elementos de la vista, en la consulta, al definir la edición de elementos de la vista y al guardar los datos del formulario en base de datos.

...
...
//
// Elementos de la vista
//
private EditText nombre;
private EditText condiciones;
private EditText contacto;
private EditText telefono;
private EditText email;
private EditText observaciones;
private CheckBox pasivo ;
...
...
//
// Obtenemos los elementos de la vista
//
nombre = (EditText) findViewById(R.id.nombre);
condiciones = (EditText) findViewById(R.id.condiciones);
contacto = (EditText) findViewById(R.id.contacto);
telefono = (EditText) findViewById(R.id.telefono);
email = (EditText) findViewById(R.id.email);
observaciones = (EditText) findViewById(R.id.observaciones);
pasivo = (CheckBox) findViewById(R.id.pasivo);
...
...
private void consultar(long id)
{
    //
    // Consultamos el centro por el identificador
    //
    cursor = dbAdapter.getRegistro(id);
    
    nombre.setText(cursor.getString(cursor.getColumnIndex(HipotecaDbAdapter.C_COLUMNA_NOMBRE)));
    condiciones.setText(cursor.getString(cursor.getColumnIndex(HipotecaDbAdapter.C_COLUMNA_CONDICIONES)));
    contacto.setText(cursor.getString(cursor.getColumnIndex(HipotecaDbAdapter.C_COLUMNA_CONTACTO)));
    telefono.setText(cursor.getString(cursor.getColumnIndex(HipotecaDbAdapter.C_COLUMNA_TELEFONO)));
    email.setText(cursor.getString(cursor.getColumnIndex(HipotecaDbAdapter.C_COLUMNA_EMAIL)));
    observaciones.setText(cursor.getString(cursor.getColumnIndex(HipotecaDbAdapter.C_COLUMNA_OBSERVACIONES)));
    pasivo.setChecked(cursor.getString(cursor.getColumnIndex(HipotecaDbAdapter.C_COLUMNA_PASIVO)).equals("S"));
}
...
...
private void setEdicion(boolean opcion)
{
    nombre.setEnabled(opcion);
    condiciones.setEnabled(opcion);
    contacto.setEnabled(opcion);
    telefono.setEnabled(opcion);
    email.setEnabled(opcion);
    observaciones.setEnabled(opcion);
    pasivo.setEnabled(opcion);
}
...
...
private void guardar()
{
	//
	// Obtenemos los datos del formulario
	// 
	ContentValues reg = new ContentValues();
	
	//
	// Si estamos en modo edición añadimos el identificador del registro que se utilizará en el update
	//
	if (modo == Hipoteca.C_EDITAR)
		reg.put(HipotecaDbAdapter.C_COLUMNA_ID, id);
	
	reg.put(HipotecaDbAdapter.C_COLUMNA_NOMBRE, nombre.getText().toString());
	reg.put(HipotecaDbAdapter.C_COLUMNA_CONDICIONES, condiciones.getText().toString());
	reg.put(HipotecaDbAdapter.C_COLUMNA_CONTACTO, contacto.getText().toString());
	reg.put(HipotecaDbAdapter.C_COLUMNA_TELEFONO, telefono.getText().toString());
	reg.put(HipotecaDbAdapter.C_COLUMNA_EMAIL, email.getText().toString());
	reg.put(HipotecaDbAdapter.C_COLUMNA_OBSERVACIONES, observaciones.getText().toString());
	reg.put(HipotecaDbAdapter.C_COLUMNA_PASIVO, (pasivo.isChecked())?"S":"N");
	
	if (modo == Hipoteca.C_CREAR)
	{
		dbAdapter.insert(reg);
		Toast.makeText(HipotecaFormulario.this, R.string.hipoteca_crear_confirmacion, Toast.LENGTH_SHORT).show();
	}
	else if (modo == Hipoteca.C_EDITAR)
	{
		Toast.makeText(HipotecaFormulario.this, R.string.hipoteca_editar_confirmacion, Toast.LENGTH_SHORT).show();
		dbAdapter.update(reg);
	}
	
	//
	// Devolvemos el control
	//
	setResult(RESULT_OK);
	finish();
}
...
...

 

4: Resaltar elemento en ListView

Vamos a mostrar los elementos que estén pasivos con color gris en el ListView. Para ello modificamos el método bindView de la clase HipotecaCursorAdapter.

...
...
@Override
public void bindView(View view, Context context, Cursor cursor)
{      
    TextView tv = (TextView) view ;
    
    tv.setText(cursor.getString(cursor.getColumnIndex(HipotecaDbAdapter.C_COLUMNA_NOMBRE)));

    if (cursor.getString(cursor.getColumnIndex(HipotecaDbAdapter.C_COLUMNA_PASIVO)).equals("S"))
    {
        tv.setTextColor(Color.GRAY);
    }
    else
    {
        tv.setTextColor(Color.BLACK);
    }
}
...
...

 

5: Ejecución de la aplicación

¡Ya está todo listo! Ahora basta con ejecutar la aplicación en el emulador.

android_sqlite_upgrade_2


 
Si tienes alguna pregunta o algo que aportar no lo dudes … ¡tienes los comentarios a tu disposición!