Persistence 

de DONNEES


Jérôme Baton,17 juin 2013
@wadael
Barcamp DroidCon FR

Qui suis-JE ?



Plein d'années de Java (côté serveur)
Android Fanboy et codeur depuis platform 3 
(le soir et le dimanche)

Auteur de l'article 
"ORMLite: un ORM pour Android"
publié dans Linux Magazine France (juillet 2012)

Mon twitter  @wadael
www.wadael.org

PERSISTER LES DONNEES PArce que ...


Parfois, il faut stocker des informations utiles sur le téléphone ...

Et pouvoir y accéder à nouveau.


Exemple: 
application mobile de terrain 
pour prendre des commandes : le catalogue de produits ne doit pas être téléchargé à chaque visite de prospect

Même SI 

  • Capacité de stockage réduite
  • Un terminal cela peut disparaître
    • Casse
    • Vol
  • MAJ des données
    • comment faire si absence de réseau

D'autre raisons plus classiques
  • gestion des MAJ entre le mobile et le serveur
    • date synchro != date MAJ

Perte des donnees



Ce sujet n'est pas dans la cadre de ce talk.

Stockage LOCAL



Ces slides seront uniquement consacrées 
au stockage local

Les options de bases

Pour stocker de la data

Package SQL : android.database.sqlite
 
Sinon, à l'ancienne, à la dure

 static final String[] lesContreps ={	
		"La pièce du fond",
		"Salut Fred",
		"il fait chaud et beau",
		"La philantropie de l'ouvrier charpentier",
		"Art de décaler les sons",....
Dans une classe statique

Android.SQLITE


Franchement, ....
Du code pas très excitant ...

Donne l'impression de faire du JDBC à la mano

A L'ANCIENNE



Une option à ne considérer que pour un jeu de données fixe, sans aucune modification.
 

Ce qui n'arrive pas dans la vraie vie :)

LES OPTIONS FOLLES



DYI: Faire son propre framework 
de stockage de données

Ecrire dans des fichiers (texte, obj. sérialisés, json,...), 
 éventuellement avec un XOR

Utiliser une BDD de type graphe 
(Neo4J a une version Android ... GPL)

NoSQL ?


Key/Value 

DIY
Waspdb
TouchDB-Lucene
...

LES OPTIONS EVOLUEES


Utiliser un ORM.
Parmi les options

TRES EVOLUEES

Evoluées en fonctionnalités
Du lourd !

Hibernate
et son concurrent 
BatooJPA


Pour avoir du JPA ...
Le même que sur le serveur : des Mo  de dépendances ...

MON CHOIX : ORMLITE


Déjà éprouvé hors Android, bien documenté

Méthode 1 : Des annotations à ajouter 
OU

Méthode 2 : Méthode 1 
ET 
un fichier de configuration à générer



ExeMPLE de code

@DatabaseTable(tableName = "farma")
public class Pharmacie implements Serializable {
...
	@DatabaseField(generatedId = true, index = true, columnName = Fields.ID)
	Integer id;

	@DatabaseField(columnName = Fields.NOM)
	public String nom;

	@DatabaseField(columnName = Fields.ADRESSE)
	public String adresse;

	@DatabaseField(foreign = true, foreignAutoRefresh = true, foreignAutoCreate = true, columnName = Fields.VILLE)
	Ville ville;

	@DatabaseField(columnName = Fields.LATITUDE)
	public Double lat;

	@DatabaseField(columnName = Fields.LONGITUDE)
	public Double longi;
....

GET STARTED

Lisez LMF hors série n°61

http://www.ed-diamond.com/produit.php?ref=lmhs61&id_rubrique=2&caracteristique=1-2-&caracdisp=2-4-
Google : "un ORM pour Android"



Désolé pour la pause publicitaire

:)

BECOME A NINJA


La documentation officielle est détaillée


RTFM + experience


Inconvénient MAJEUR

(Pour moi)


PAS DU JPA :(


Le monde serait si tellement plus beau si le backend et le mobile partageaient les classes du modèle métier

Ou pas (raisons de sécurité)

Des annotations pas "standard"  :-(
Mais quand même @Entity, @Id et @Column

Une difference NOTABLE :)


Une @Entity JPA (TopLink et autres) persiste par défaut tous ses champs.

Dans un objet @DatabaseTable il faut annoter chaque champs à persister.
Par défaut, aucun champs n'est persisté


Ultérieurement, je ferais un article plus détaillé sur mon 
http://blog.wadael.org 

ET SINON ... L'Option MACGYVER


Faire générer les objets 'ormlite' à partir des POJO JPA.
Ou inversement

Un programme maison à intégrer dans son build 


Simplement du remplacement de texte

Astuces



Quelques astuces pour assurer

Utiliser la méthode 2



Les annotations servent pour générer un fichier de conf. qui est utilisé par le Helper


public DatabaseHelper(Context context) {super(context, DATABASE_NAME, null, DATABASE_VERSION , R.raw.ormlite_config);

De  @kPGALLIGAN


Keep a single SQLiteOpenHelper instance in a static context.  
Do lazy initialization, and synchronize that method.  
When do you close it?  You don’t.  When the app shuts down, it’ll let go of the file reference, if its even holding on to it.


 public class DatabaseHelper extends OrmLiteSqliteOpenHelper
{
    private static DatabaseHelper instance;

    public static synchronized DatabaseHelper getHelper(Context context)
    {
        if (instance == null)
            instance = new DatabaseHelper(context);

        return instance;
    }
//Other stuff... 
}
Il a écrit la partie pour Android

Créez VOS DAO



Mettez y vos méthodes métier pour centraliser le code d'accès aux données


As usual

DEFINIR DES CONSTANTES


Pour les noms des tables et des champs
afin de bénéficier de la complétion de votre IDE 
pour écrire les requêtes

  public interface Fields { 
    	public static final String NOMTABLE="pharma";        public static final String NOM="NOM";        public static final String CODEPOSTAL="CODEPOSTAL"; ... 

permet d'écrire 

  queryBuilder.where().eq(Fields.NOM, "foo")
  .and()
  .eq(Fields.CODEPOSTAL, "78150");
qui équivaut à
SELECT * FROM pharma WHERE (nom = 'foo' AND codepostal = '78150')
Mais, en bénéficiant de l'auto-completion lors de l'écriture.

Je recommande de créer une interface "Fields" à mettre dans chaque objet du modèle métier.  Et de faire de même dans chaque objet métier 

Avoir un modele SIMPLE


Afin de bénéficier du chargement complet des objets fils persistants de façon transparente tout en gardant des performances correctes (remember l'effet grappe)
 public class Pharmacie {...@DatabaseField(foreign = true, foreignAutoRefresh = true, foreignAutoCreate = true, columnName = Fields.VILLE)
	Ville ville;
...}
Sinon, il faut l'écrire soit même
(d'où l'intérêt de la couche DAO personnalisée)
et alors à quoi bon un ORM ?

DES QUESTIONS ?






FIN


PS:     Je cherche un job passionnant 
si vous avez cela, contactez moi 

@wadael
wadael sur gmail com
Jérôme Baton sur Viadeo/LinkedIn
Made with Slides.com