«

»

oct 24 2011

Android DataFramework, creando la estructura de la Base de Datos

Al hora de añadir bases de datos SQLite a nuestras apps nos encontramos con que la manera de hacerlo no es trivial y no carente de cierta dificultad, llegando a tener que crear varias clases java para su existencia y uso. No es que sea una tarea titanica pero si que se agradece encontrar perlas como estas que nos ayuden en nuestros dia a dia como desarrollador. Hoy tenemos que agradecerle a @Javielinux (creador de TweetTopics) la existencia de esta libreria que nos facilitara muy mucho la inclusion de bases de datos en nuestros desarrollos para Android.
 

 
Mediante esta librería se podrá gestionar una base de datos SQLite dentro Android de una manera sencilla. Simplemente tendremos que escribir un archivo XML y la librería se encargará de crear las tablas y ofrecernos una API mediante la cual podremos crear, modificar y eliminar registros de una manera sencilla y eficaz en nuestra aplicación.
 

Creando la estructura de la Base de Datos

Con Android DataFramework no tenemos que crear las sentencias SQL para creación de tablas, la librería se encarga de esta tarea mediante la estructura de los archivos XML. El sistema se encargará, la primera vez que se abre la aplicación, de crear las base de datos y las tablas. Además tendremos la posibilidad de hacer una carga de registros en las tablas en cada versión de la base de datos mediante otro fichero XML.

Los ficheros XML se tiene que guardar dentro de los recursos de nuestro proyecto en res/xml y deben tener un nombre que no podrá cambiarse. Estos serán:
 

  • “tables.xml”: contiene la estructura de las tablas.
  • “initialvalues_v[version].xml”: contiene los registros que queremos que se cargen en cada versión.

 

Estructura de tables.xml

Un archivo tables.xml podría ser este:
 

<database name="notes_db" version="1">
    <table name="notes" to-string="%title%">
        <field name="title" obligatory="true" type="text" size="128"/>
        <field name="body" obligatory="true" type="text"/>
        <field name="category_id" type="foreign-key" foreign-table="categories" />
    </table>
    <table name="categories" to-string="%name%">
        <field name="name" obligatory="true" type="name" size="128"/>
    </table>
</database>

 

Nueva base de datos llamada “notes_db” tendrá dos tablas: “notes” y “categories”. El nodo “database” tiene el nombre de la base de datos y la versión de esta. En nuevas versiones de la base de datos podremos añadir nuevas tablas y nuevos campos a las tablas. El trabajo con versiones se explicará en otro post.

Dentro de “database” tendremos tantos nodos “table” como tablas tenga nuestra base de datos, y dentro de “table” tendremos los campos (nodos field).

Es importante saber que todas las tablas tienen un campo llamado “_id” que es clave primaria y es numérico y autoincrementado (aunque desde el objeto Entity es posible forzar el identificador si fuera necesario).

 
Nodo table

Este nodo contiene la información de la tabla. Tiene dos atributos:
 

  • name: Nombre de la tabla.
  • to-string: Formato que devolverá el método toString() de la instancia Entity que tenga como modelo esta tabla.

 
Nota: En el formato de “to-string” podremos usar los campos de la tabla poniendo el nombre entre símbolos “%”

 
Nodo field

Este nodo tendrá la información sobre los campos. Tiene los atributos siguientes:
 

  • name: Nombre del campo.
  • obligatory: Si es obligatorio (true | false).
  • size: Tamaño del campo (en caso que sea de tipo “text”).
  • type: Tipo del campo. Puede ser: text, integer, foreign-key, double y float.
  • foreign-table: En el que sea de tipo “foreign-key” este campo contiene el nombre de la tabla a la que la relaciona.

 
Existe un tipo especial llamado string-identifier. Este tipo es una cadena que corresponde a una clave del archivo string.xml de tu aplicación Android. Cuando se hace un getString(“nombrecampo”) devolverá el valor del recurso en _string.xml en el caso que exista, o el recurso en sí en el caso de no encontrarse.

Esto puede ser interesante para campos multiidioma.

También existe un tipo especial llamado drawable-identifier que contiene un recurso drawable del proyecto y que se puede obtener directamente de la clase Entity con el método getDrawable(“nombre_campo”).

 

Estructura de initialvalues_v(version).xml

Este archivo XML nos servirá para insertar una serie de valores en la tablas en cada versión si fuese necesario. Puede ser útil para rellenar tablas con categorías, por ejemplo.

Un ejemplo sería este:

 

<values>
    <row table="categories" id="1">
        <field name="name" value="Sin categoria" />
    </row>
    <row table="categories" id="2">
        <field name="name" value="Familia" />
    </row>
    <row table="categories" id="3">
        <field name="name" value="Amigos" />
    </row>
</values>

 

El nodo “values” contiene nodos “row” que equivalen a una fila dentro de la base de datos.

El nodo “row” tiene dos atributos:

  • table: Tabla en la que se quiere insertar el registro.
  • id: Identificador del registro. En el caso de no tener este atributo será un valor autoincrementado.

Los nodos “field” representan a los campos del registro y tiene los siguientes atributos:

  • name: Nombre del campo.
  • value: Valor del campo.

 

Trabajar con versiones de la base de datos

Android DataFramework soporta el trabajo con diferentes versiones de la base de datos. SQLite no soporta ni modificar ni eliminar campos de las tablas, por lo que sólo podemos añadir tablas y campos a estas.

El nodo database de tables.xml tiene un atributo llamado version que corresponde a la versión actual de la base de datos. Este parámetro se comprueba cada vez que se abre el programa y sino corresponde con la versión actual, se harán los cambios pertinente. Todo esto es transparente para el usuario y el programador que sólo tendrá que modificar el archivo tables.xml.

El atributo version es un número entero y autoincrementado. Para poder añadir campos o tablas a la base de datos sólo tenemos que añadir el atributo new-in-version al nodo table (en el caso que queramos añadir una tabla nueva) o al nodo field (en el caso que queramos añadir un campo nuevo a una tabla ya existente).

Imaginamos que queremos añadir un nuevo campo llamado importance_id con la importancia de nueva nota y que será una clave foránea a una nueva tabla que tiene los valores de importancia llamada importance.

Los cambios serían los siguientes:

 

<database name="notes_db" version="2">

  <table name="notes" to-string="%title%">
    <field name="title" obligatory="true" type="text" size="128"/>
    <field name="body" obligatory="true" type="text"/>
    <field name="category_id" type="foreign-key" foreign-table="categories" />
    <field name="importance_id" type="foreign-key" foreign-table="importance" new-in-version="2" />
  </table>

  <table name="categories" to-string="%name%">
    <field name="name" obligatory="true" type="name" size="128"/>
  </table>

  <table name="importance" to-string="%name%" new-in-version="2">
    <field name="name" obligatory="true" type="name" size="128"/>
  </table>

 </database>

 

Una vez hecho esto podremos añadir valores a nuestras nuevas tablas y campos en esta versión usando initialvalues_v2.xml en nuestro caso tal y como se comentó con anterioridad.

 
NOTA: Si el cambio de versión es mayor a 1, o sea, imaginamos que pasamos de la versión 2 a la versión 5, Android DataFramework hará todos los cambios uno a uno, en este caso los de la versión 3, luego la 4 y 5.

 

Soporte multiidioma

Con esta característica podremos tener campos en la base de datos con diferentes idiomas. Por ejemplo podemos tener un campo “title” y según el idioma que tengamos en nuestro teléfono devolvernos un idioma u otro.

Lo primero es modificar el “tables.xml”. En el nodo “database” ponemos los lenguajes con los que queremos que trabaje nuestra base de datos separados con “|” en el atributo “languages”
 

<database name="nombre_db" version="1" languages="es|en|de">

 

En esta caso sería español, inglés y alemán. Luego definimos cada campo que queremos que sea multilenguaje.

 

<field name="titulo" obligatory="true" type="multilanguage" />

 

Internamente, y de forma transparente para el programador, creará 3 campos “titulo_es”, “titulo_en” y “titulo_de”, donde se guardarán los valores en cada uno de los idiomas.

Por defecto cuando intentemos recoger la información del campo título, nos dará el idioma que tengamos definido en nuestro móvil (en los Locale de Android). Para ello es necesario que los idiomas estén en la ISO 639-1 como en el ejemplo que estamos trabajando.

Para recoger la información lo hacemos como siempre getString(“titulo”), NO tenemos que poner getString(“titulo_es”) ya que no funcionaría.

También podemos forzar un idioma con:

 

DataFramework.getInstance().setForceLanguage("en");

 

Y con esto estamos servidos por hoy, espero que os resulte interesante, en un proximo post os explicaremos como usarla en nuestras activities.
 
fuente | https://github.com/javipacheco/Android-DataFramework
web del autor | El blog de Javielinux

Libreria | Descarga

 

Acerca del autor

JMPergar

Mobile Developer at @BeRepublic & Founder of @AndroCode. Silver Speaker & Member of Core Team at @GDGBarcelona.

  • http://www.hellovierco.com Vierco

    Esto es de las cosas más útiles que me he encontrado
    Genial trabajo :)

    • http://hackedbrain.blogspot.com/ JMPergar | Editor Jefe

      Totalmente de acuerdo, facilita el trabajo que es una barbaridad.

  • Iván

    Magnifica librería, la probare lo antes posible, pero me surge una pregunta, ¿al revés hay algo similar? es decir, de una bbdd SQLite que ya tengamos y queramos modificar por la razon que sea ¿se podrían generar los XML que son mucho mas legibles segun parece?

    • http://hackedbrain.blogspot.com/ JMPergar | Editor Jefe

      No tenemos conocimiento de ninguna libreria parecida pero ten por seguro que se cruza en nuestro camino os informaremos de ello.

  • Pingback: Usando Android-DataFramework en nuestro proyecto | Androcode()

  • http://@royalbeats royalbeats

    Super útil!! yo que soy programador novel en Java y Android, acabo de alucinar con la simplicidad de esta libreria!! muy bien explicado jefes! 1 abrazo

  • jose

    una pregunta como puedo saber que tipo de libreria tiene el metodo getEntityListCount en dataframework por k me aparese como error getEntityListCount

    • http://hackedbrain.blogspot.com/ JMPergar | Editor Jefe

      tipo de libreria? Lo siento, no te entiendo

  • Angels

    Hola! soy nueva en la programación Android, y no me queda muy claro como incluir la librería en mi proyecto.

    Podrías indicarmelo.

    Un saludo, y muchas gracias.

  • Squall

    Hola, estoy desarrollando una aplicacion la cual debe conectarse con una base de datos mysql para obtener unos datos. Mi pregunta es, que si existe alguna forma de copiar una tabla de una base de datos mysql y crearla con esta libreria, , de forma que pueda hacer las consultas con esta libreria tan util.

    Un saludo y gracias por toda la informacion ^^

    • http://www.linkedin.com/in/jmpergar JMPergar

      Pues la verdad es que hace mucho que probe esta librería y no he llegado a usarla en profundidad, finalmente opte por usar ADA Framework de la cual tambien tenemos tutoriales en el blog. No lo he hecho, pero diría que es posible hacer lo que dices. Si preguntas tus dudas en estos post quizas el FedeProEx pueda contestarte.

  • Gabriel

    Hola por favor si me podrias ayudar con esta librería lo que pasa es que ya puedo crear, ingresar valore y todo correctamente en la tabla pero lo que no me queda claro es como ingreso la parte de foreign-key para relacionar dos tablas yo estaba poniendo ent.setValue(“category_id” , 2); siendo category_id mi campo tipo foreing-key y el número 2 es el “id” especificado en initialvalues_v1.xml tal como se especifica en este tutorial, haciendo de la forma que la hago no logro que se relacionen las tablas entonces no se en que estoy falland, por favor si me puedes ayudar en eso.
    Gracias

  • MILTON MORILLO M.

    Muy bueno tu pagina amigo espero sigas así ayudando al publico gracias..