-
Notifications
You must be signed in to change notification settings - Fork 3
Base de datos
En android se pueden guardar información de diferentes maneras, pero en este caso utilizaremos bases de datos. Usaremos SQLite, el sistema por defecto para android. En esta parte del tutorial no se ahondará de sobremanera debido a que es un tema transversal y hay mucha documentación al respecto.
-
Definir un esquema y sus constantes
-
Crear base de datos y tablas
-
Crear métodos CRUD
Una vez que el modelo relacional esté definido este se debe plasmar en
una clase que llamaremos DatabaseContract
. Esta tendrá definidas como
String los nombres de las tablas, de las columnas y algunas operaciones
importantes. Gracias a esto podemos cambiar el nombre de, por ejemplo,
una columna sin la necesidad de cambiar el resto de nuestro código.
// DatabaseContract.java
public final class DatabaseContract {
public DatabaseContract() {
}
public static abstract class Students implements BaseColumns {
// BaseColumns nos entrega las constantes \_ID y \_COUNT
public static final String TABLE_NAME = "STUDENTS";
public static final String COLUMN_NAME_STUDENT_NAMES = "names";
public static final String COLUMN_NAME_FIRST_LASTNAME = "firstlastname";
public static final String COLUMN_NAME_SECOND_LASTNAME = "secondlastname";
public static final String COLUMN_ID_CLOUD = "idcloud";
public static final String TEXT_TYPE = " TEXT";
public static final String INTEGER_TYPE = " INTEGER";
public static final String COMMA_SEP = ",";
public static final String SQL_CREATE_STUDENTS_TABLE =
"CREATE TABLE " + Students.TABLE_NAME + " (" +
Students.\_ID + " INTEGER PRIMARY KEY," +
Students.COLUMN_NAME_STUDENT_NAMES + TEXT_TYPE + COMMA_SEP +
Students.COLUMN_NAME_FIRST_LASTNAME + TEXT_TYPE + COMMA_SEP +
Students.COLUMN_NAME_SECOND_LASTNAME + TEXT_TYPE + COMMA_SEP+
Students.COLUMN_ID_CLOUD + INTEGER_TYPE +
" )";
public static final String SQL_DELETE_STUDENTS =
"DROP TABLE IF EXISTS " + Students.TABLE_NAME;
}
}
Ahora utlizaremos la clase SQLiteOpenHelper
, una API para poder
interactuar con nuestra base de datos de manera lazy. Esto quiere
decir que la base de datos, o la conexión con ella, es creada solo en
caso de ser necesitada. Esto ocurrirá cuando se llame a
getWritableDatabase()
o a getReadableDatabase()
.
Las instancias de SQLiteDatabase retornadas por estos métodos están
especialmente configuradas para realizar las operaciones especificadas.
Esto quiere decir que getWritableDatabase()
retornará una instancia en
el que la escritura de datos será rápida en desmedro de la lectura. En
cambio, con getReadableDatabase()
se tendrá una lectura más rápida.
Además, al llamar a estos métodos se crea la base de datos en caso de no
existir aún.
Otro método esencial es onCreate(SQLiteDatabase)
. Ahí es donde se
ejecuta el código SQL para crear las tablas de la base de datos.
// StudentsDbHelper.java
// Documentacion:
// http://developer.android.com/reference/android/database/sqlite/SQLiteOpenHelper.html
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class StudentsDbHelper extends SQLiteOpenHelper {
public static final int DATABASE_VERSION = 1;
public static final String DATABASE_NAME = "Students.db";
private static StudentsDbHelper sInstance;
private StudentsDbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
// Nos aseguramos de que solo haya una instancia para evitar errores.
// Mas detalles:
// http://www.androiddesignpatterns.com/2012/05/correctly-managing-your-sqlite-database.html
public static synchronized StudentsDbHelper getInstance(Context context) {
if (sInstance == null) {
sInstance = new StudentsDbHelper(context.getApplicationContext());
}
return sInstance;
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(DatabaseContract.Students.SQL_CREATE_STUDENTS_TABLE);
}
// Cambia la version del esquema en caso de haber modificaciones.
// Por simplicidad asumimos que esto no va a pasar y tan solo se resetea la db.
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL(DatabaseContract.Students.SQL_DELETE_STUDENTS);
onCreate(db);
}
}
Para escribir en la base de datos se debe obtener una instacia de
StudentsDbHelper
para luego obtener una de la base de datos adaptada
para escritura.
StudentsDbHelper mDbHelper = StudentsDbHelper.newInstance();
SQLiteDatabase db = mDbHelper.getWritableDatabase();
Para leer se debe obtener una instancia adaptada para la lectura.
StudentsDbHelper mDbHelper = StudentsDbHelper.newInstance();
SQLiteDatabase db = mDbHelper.getReadableDatabase();
Para insertar datos se deben ingresar los datos del elemento a añadir en
ContentValues y usar el método insert. El segundo argumento especifica
la columna en que la base de datos puede puede insertar null
si values
(los datos a ingresar) está vacio. Si es que no quieres que se ingrese
un record con valores vacios debes setearlo como null
. Por ejemplo, si
se quiere añadir un estudiante:
// Codigo para insertar nuevo estudiante
if (mDbHelper == null) {
mDbHelper = StudentsDbHelper.getInstance(getActivity());
}
SQLiteDatabase db = mDbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(DatabaseContract.Students.COLUMN_NAME_STUDENT_NAMES, student.getNames());
values.put(DatabaseContract.Students.COLUMN_NAME_FIRST_LASTNAME, student.getFirstLastname());
values.put(DatabaseContract.Students.COLUMN_NAME_SECOND_LASTNAME, student.getSecondLastname());
values.put(DatabaseContract.Students.COLUMN_ID_CLOUD, student.getIdCloud());
// Retorna la columna en la que fue insertado
long success = db.insert(
DatabaseContract.Students.TABLE_NAME,
null,
values);
if (success >= 0) return true;
return false;
Para consultar datos se usa el método query()
. Si no se quiere filtrar y
solo obtener toda la información de la tabla se pueden dejar todos los
valores como null
excepto el nombre de la tabla. Por ejemplo para
seleccionar todos los estudiantes:
// Codigo para seleccionar todos los estudiantes
if (mDbHelper == null) {
mDbHelper = StudentsDbHelper.getInstance(getActivity());
}
// Selecciono las columnas que debe retornar de cada fila. Podria dejarse como null y me retorna todas.
String[] projection = {DatabaseContract.Students.COLUMN_NAME_STUDENT_NAMES,
DatabaseContract.Students.COLUMN_NAME_FIRST_LASTNAME,
DatabaseContract.Students.COLUMN_NAME_SECOND_LASTNAME,
DatabaseContract.Students.COLUMN_ID_CLOUD
};
// Se deja como null porque no se requiere filtrar. Por ejemplo, si se necesitara filtrar por primer apellido:
// String selection = DatabaseContract.Students.COLUMN_NAME_FIRST_LASTNAME + "= ?"
String selection = null;
// Que el primer apellido sea Perez:
// String[] selectionArgs = new String[]{ "Perez" };
// En este caso dejamos como null
String[] selectionArgs = null;
SQLiteDatabase db = mDbHelper.getReadableDatabase();
Cursor c = db.query(DatabaseContract.Students.TABLE_NAME, // Tabla
projection, // Columnas a retornar
selection, // Columnas de WHERE
selectionArgs, // Valores de WHERE
null, // Group by
null, // Filtro por columnas de grupos
DatabaseContract.Students.COLUMN_NAME_FIRST_LASTNAME +" ASC"); // Ordenados
ArrayList<Student> studentsInDb = new ArrayList<Student>();
c.moveToFirst();
if (c.getCount()<1){
return false;
}
while (c.moveToNext()){
String names = c.getString(c.getColumnIndexOrThrow(DatabaseContract.Students.COLUMN_NAME_STUDENT_NAMES))
.toUpperCase();
String firstLast = c.getString(c.getColumnIndexOrThrow(DatabaseContract.Students.COLUMN_NAME_FIRST_LASTNAME))
.toUpperCase();
String secondLast = c.getString(c.getColumnIndexOrThrow(DatabaseContract.Students.COLUMN_NAME_SECOND_LASTNAME))
.toUpperCase();
int idCloud = c.getInt(c.getColumnIndexOrThrow(DatabaseContract.Students.COLUMN_ID_CLOUD));
studentsInDb.add(new Student(names, firstLast, secondLast, idCloud));
}
Se utiliza el método delete.
Se utiliza el método update.
Siguiente: Content Provider.