Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Room ou Realm : Quelle base de données pour vos applications Android ?

1,040 views

Published on

Lors de la dernière I/O 2017, Google a annoncé la mise à disposition aux développeurs d'un ensemble de d'outils et composants regroupés sous le nom "Android Architecture Components".

Le but est d'aider les développeurs à développer des applications robustes, testables et maintenables permettant notamment de manipuler les données et intervenir sur le cycle de vie des écrans.

Dans le cadre de cette présentation, nous allons plus particulièrement nous intéresser au module "Room", une couche d'abstraction à SQLite (ORM) permettant de manipuler la base de données des applications et assurer la persistance des données.

Puisque Realm est aujourd'hui à la mode mais présente des limitations, nous comparerons les deux outils sur plusieurs angles :

• configuration
• gestion d'une entité avec une relation
• écriture des requêtes
• rapidité d'exécution
• gestion de la migration
• etc.

Nous verrons ainsi si Room est, à ce stade, prometteur ou si au contraire, Realm a encore de beaux jours devant lui.

Published in: Software
  • Be the first to comment

Room ou Realm : Quelle base de données pour vos applications Android ?

  1. 1. Room VS Realm PAUG - 29 novembre 2017
  2. 2. Smart&Soft Agence Digitale 2017 2 Sommaire ROOM VS REALM • La base de données historique : SQLite • Présentation d’un ORM • Comparaison de Realm et Room
  3. 3. SQLite
  4. 4. Smart&Soft Agence Digitale 2017 4 Définition SQLite “Bibliothèque [...] qui propose un moteur de base de données relationnelle accessible par le langage SQL” Source : https://fr.wikipedia.org/wiki/SQLite
  5. 5. Smart&Soft Agence Digitale 2017 5 Avantages SQLite • SQL • Base de données embarquée • SGBD complet : • gestion des transactions • gestion des triggers • gestion des vues • etc.
  6. 6. Smart&Soft Agence Digitale 2017 6 Inconvénients SQLite • SQL • Comment faire de l’objet ? • pattern DAO • pattern repository • etc.
  7. 7. Qu’est-ce qu’un ORM ?
  8. 8. Smart&Soft Agence Digitale 2017 8 Définition ORM “Un mapping objet-relationnel est une technique de programmation informatique qui crée l'illusion d'une base de données orientée objet à partir d'une base de données relationnelle en définissant des correspondances entre cette base de données et les objets du langage utilisé” Source : https://fr.wikipedia.org/wiki/Mapping_objet-relationnel
  9. 9. Smart&Soft Agence Digitale 2017 9 Quelques ORM ORM • ORMLite : http://ormlite.com/ • ActiveAndroid : http://www.activeandroid.com/ • GreenDAO : http://greenrobot.org/greendao/ • SugarORM : http://satyan.github.io/sugar/ • Freezer : https://github.com/florent37/Freezer
  10. 10. Smart&Soft Agence Digitale 2017 10 Dans les autres OS ORM Entity Framework Core Core Data
  11. 11. Room VS Realm
  12. 12. 2017 12 Définitions 1. Quelques définitions
  13. 13. Smart&Soft Agence Digitale 2017 13 Définition Realm “Realm Mobile Database is an alternative to SQLite and Core Data. Thanks to its zero-copy design, Realm Mobile Database is much faster than an ORM, and often faster than raw SQLite.” Source : https://realm.io/products/realm-mobile-database/
  14. 14. Smart&Soft Agence Digitale 2017 14 Définition Room “Room provides an abstraction layer over SQLite to allow fluent database access while harnessing the full power of SQLite.” Source : https://developer.android.com/topic/libraries/architecture/room.html
  15. 15. 2017 15 Architecture 2. Architecture
  16. 16. 2017 16 Smart&Soft Agence Digitale Room ARCHITECTURE • Fonctionne par-dessus SQLite • Fonctionne avec 3 éléments : • Database • Entity • DAO • Copie les éléments de la base de données vers des objets
  17. 17. 2017 17 Smart&Soft Agence Digitale Realm ARCHITECTURE • Système de références • Travail avec un arbre • Fonctionne à partir d’objets “Proxy” • Promesse de “zero copy” • Promesse de rapidité
  18. 18. 2017 18 Comparaison 3. Comparaison
  19. 19. Smart&Soft Agence Digitale 2017 19 Les points de comparaison COMPARAISON 1. Configuration 2. Gestion d’une entité avec des relations 3. Les requêtes 4. Rapidité d’exécution 5. Gestion de la migration 6. D’autres éléments (RxJava, poids, nombre de méthodes, threading, etc.)
  20. 20. 2017 20 Smart&Soft Agence Digitale Realm 1. CONFIGURATION 1. Ajout d’une dépendance dans le fichier build.gradle du projet dependencies { classpath "io.realm:realm-gradle-plugin:4.2.0" } 2. Application du plugin dans le fichier build.gradle du module apply plugin: "realm-android" 3. Initialisation de Realm Realm.init(this); Realm.setDefaultConfiguration( new RealmConfiguration.Builder().deleteRealmIfMigrationNeeded().schemaVersion(1).build());
  21. 21. 2017 21 Smart&Soft Agence Digitale Room 1. CONFIGURATION 1. Ajout d’une nouvelle source dans le fichier build.gradle du projet maven { url "https://maven.google.com" } // google() 2. Ajout des dépendances dans le fichier build.gradle du module compile("android.arch.persistence.room:runtime:1.0.0") annotationProcessor("android.arch.persistence.room:compiler:1.0.0") 3. Initialisation de Room à remettre à plus tard !
  22. 22. 2017 22 2. Gestion d’une entité avec des relations COMPARAISON
  23. 23. 2017 23 Smart&Soft Agence Digitale Realm 2. Gestion d’une entité avec des relations public class RealmCat extends RealmObject { @PrimaryKey private int id; private int age; private String name; //Getters and setters } public class RealmDog extends RealmObject { public enum RealmColor { Black, White } @PrimaryKey private int id; private int age; private String name; private String color; //Getters and setters public RealmColor getRealmColor() { return color != null ? RealmColor.valueOf(color) : null; } public void setRealmColor(RealmColor color){ this.color = color.toString(); } }
  24. 24. 2017 24 Smart&Soft Agence Digitale Realm 2. Gestion d’une entité avec des relations public class RealmPerson extends RealmObject { @PrimaryKey private int id; private String name; private RealmList<RealmDog> dogs; private RealmList<RealmCat> cats; //Getters and setters }
  25. 25. 2017 25 Bilan provisoire 2. Gestion d’une entité avec des relations • Modélisation très simple • Gestion des relations efficaces • Héritage impossible (contournement possible via des objets composites) • Pas d’auto-incrémentation de la clef primaire • Pas de gestion des énumérations
  26. 26. 2017 26 Smart&Soft Agence Digitale Room 2. Gestion d’une entité avec des relations public abstract class RoomAnimal { @PrimaryKey public int id; public int age; public String name; } @Entity(tableName = "cat") public final class RoomCat extends RoomAnimal { }
  27. 27. 2017 27 Smart&Soft Agence Digitale Room 2. Gestion d’une entité avec des relations @Entity(tableName = "dog") public final class RoomDog extends RoomAnimal { public enum RoomColor { Black, White } @TypeConverters(RoomColorConverter.class) public RoomColor color; } public final class RoomColorConverter { @TypeConverter public RoomColor fromString(String color) { return color != null ? RoomColor.valueOf(color) : null; } @TypeConverter public String fromRealmColor(RoomColor color) { return color.toString(); } }
  28. 28. 2017 28 Smart&Soft Agence Digitale Room 2. Gestion d’une entité avec des relations @Entity(tableName = "person") public final class RoomPerson { @PrimaryKey public int id; public String name; } public final class RoomPersonWithAnimals { @Embedded public RoomPerson person; @Relation(parentColumn = "id", entityColumn = "id", entity = RoomDog.class) public List<RoomDog> dogs; @Relation(parentColumn = "id", entityColumn = "id", entity = RoomCat.class) public List<RoomCat> cats; }
  29. 29. C’est pas fini...
  30. 30. 2017 30 Smart&Soft Agence Digitale Room 2. Gestion d’une entité avec des relations @Entity( tableName = "Person_has_Cat", primaryKeys = { "personId", "catId" }, foreignKeys = { @ForeignKey(entity = RoomPerson.class, parentColumns = "id", childColumns = "personId", onDelete = ForeignKey.CASCADE), @ForeignKey(entity = RoomCat.class, parentColumns = "id", childColumns = "catId", onDelete = ForeignKey.CASCADE) }) public final class RoomPersonCat { public int personId; public int catId; } @Entity( tableName = "Person_has_Dog", primaryKeys = { "personId", "dogId" }, foreignKeys = { @ForeignKey(entity = RoomPerson.class, parentColumns = "id", childColumns = "personId", onDelete = ForeignKey.CASCADE), @ForeignKey(entity = RoomDog.class, parentColumns = "id", childColumns = "dogId", onDelete = ForeignKey.CASCADE) }) public final class RoomPersonDog { public int personId; public int dogId; }
  31. 31. 2017 31 Bilan provisoire 2. Gestion d’une entité avec des relations • Gestion de l’auto-incrémentation de la clef primaire • Possibilité d’héritage • Modélisation plus complexe • Références d’objets impossible (https://developer.android.com/training/data-storage/room/referencing-data.html)
  32. 32. 2017 32 Smart&Soft Agence Digitale Realm 3. Les requêtes //1. Récupération d'une instance de Realm final Realm realm = Realm.getDefaultInstance(); //2. Création d'une transaction realm.beginTransaction(); //3. Exécution de la requête realm.copyToRealmOrUpdate(persons); //4. On termine la transaction et on ferme l'instance de Realm realm.commitTransaction(); realm.close(); Possibilité d’utiliser executeTransaction pour une gestion des erreurs simplifiée
  33. 33. 2017 33 Smart&Soft Agence Digitale Realm 3. Les requêtes Requête de sélection Requête de mise à jour final Realm realm = Realm.getDefaultInstance(); final RealmPerson persons = realm.copyFromRealm(realm.where(RealmPerson.class).equalTo("id", 299).findFirst()); realm.close(); final Realm realm = Realm.getDefaultInstance(); final RealmPerson persons = realm.where(RealmPerson.class).equalTo("id", 299).findFirst(); persons.setName(UUID.randomUUID().toString()); realm.close();
  34. 34. 2017 34 Smart&Soft Agence Digitale Realm 3. Les requêtes Requête de suppression final Realm realm = Realm.getDefaultInstance(); final RealmPerson persons = realm.where(RealmPerson.class).equalTo("id", 299).findFirst(); persons.deleteFromRealm(); realm.close();
  35. 35. 2017 35 Bilan provisoire 3. Les requêtes • Écriture des requêtes hyper simplifié • Possibilité de faire des requêtes dans le thread de l’UI • Résultats “vivants” par défaut (attention au threading !) • Impossibilité de faire des requêtes très fines : • Récupérer les chiens noirs d’une personne
  36. 36. 2017 36 Smart&Soft Agence Digitale Room 3. Les requêtes @Dao public interface RoomGenericDao<T> { @Insert( onConflict = OnConflictStrategy.REPLACE) void insert(T bo); @Insert( onConflict = OnConflictStrategy.REPLACE) void insertAll(T... bo); @Delete void delete(T bo); @Update void update(T bo); } @Dao public interface RoomCatDao extends RoomGenericDao<RoomCat> { @Query("SELECT * FROM cat") List<RoomCat> getAll(); @Query("SELECT * FROM cat WHERE id = :id") RoomCat findById(int id); }
  37. 37. 2017 37 Smart&Soft Agence Digitale Room 3. Les requêtes @Dao public interface RoomDogDao extends RoomGenericDao<RoomDog> { @Query("SELECT * FROM dog") List<RoomDog> getAll(); @Query("SELECT * FROM dog WHERE id = :id") RoomDog findById(int id); } @Dao public interface RoomPersonDao extends RoomGenericDao<RoomPerson> { @Query("SELECT * FROM person") List<RoomPersonWithAnimals> getAll(); @Query("SELECT * FROM person WHERE id = :id") RoomPersonWithAnimals findById(int id); }
  38. 38. 2017 38 Smart&Soft Agence Digitale Room 3. Les requêtes 1. Création d’une classe abstraite pour exposer les DAO et les entités managés @Database(entities = { RoomCat.class, RoomDog.class, RoomPerson.class, RoomPersonCat.class, RoomPersonDog.class }, version = 1, exportSchema = false) public abstract class MyRoomDatabase extends RoomDatabase { public abstract RoomCatDao roomCatDao(); public abstract RoomDogDao roomDogDao(); public abstract RoomPersonDao roomPersonDao(); } 2. Instanciation de la classe myRoomDatabase = Room.databaseBuilder(this, MyRoomDatabase.class, "myRoomDatabase").build();
  39. 39. 2017 39 Smart&Soft Agence Digitale Room 3. Les requêtes Possibilité d’utiliser runInTransaction //1. Création d'une transaction (facultatif) → Interdit dans le main thread myRoomDatabase.beginTransaction(); //2. Exécution de la requête myRoomDatabase.roomPersonDao().insertAll(person); //3. On indique que tout s’est bien passé myRoomDatabase.setTransactionSuccessful(); //4. On termine la transaction myRoomDatabase.endTransaction();
  40. 40. 2017 40 Smart&Soft Agence Digitale Room 3. Les requêtes Requête de sélection Requête de mise à jour final RoomPersonWithAnimals personWithAnimals =myRoomDatabase.roomPersonDao().findById(299); final RoomPersonWithAnimals personWithAnimals =myRoomDatabase.roomPersonDao().findById(299); personWithAnimals.person.name = UUID.randomUUID().toString(); myRoomDatabase.roomPersonDao().update(personWithAnimals.person); Requête de suppression final RoomPersonWithAnimals persons =myRoomDatabase.roomPersonDao().findById(43); myRoomDatabase.roomPersonDao().delete(persons.person);
  41. 41. 2017 41 Smart&Soft Agence Digitale Room 3. Les requêtes final List<RoomPersonWithAnimals> personsWithAnimals = new ArrayList<>(); for (int index = 0; index <NUMBER_OF_ITEMS; index++) { /*...*/ } //1. Création d'une transaction (facultatif) myRoomDatabase.beginTransaction(); //2. Insertion des éléments for (RoomPersonWithAnimals personAnimals : personsWithAnimals) { myRoomDatabase.roomPersonDao().insert(personAnimals.person); myRoomDatabase.roomCatDao().insertAll(personWithAnimals.cats.toArray(newRoomCat[personWithAnimals.cats.size()]); myRoomDatabase.roomDogDao().insertAll(personWithAnimals.dogs.toArray(newRoomDog[personWithAnimals.dogs.size()])); for (RoomCat cat : personWithAnimals.cats) { myRoomDatabase.roomPersonCatDao().insert(new RoomPersonCat(personWithAnimals.person.id, cat.id)); } for (RoomDog dog : personWithAnimals.dogs){ myRoomDatabase.roomPersonDogDao().insert(new RoomPersonDog(personWithAnimals.person.id, dog.id)); } } //3. On termine la transaction myRoomDatabase.setTransactionSuccessful(); myRoomDatabase.endTransaction();
  42. 42. 2017 42 Bilan provisoire 3. Les requêtes • Rude... • Par défaut impossibilité de faire des requêtes dans le thread de l’UI • SQL
  43. 43. 2017 43 Smart&Soft Agence Digitale 3. Les performances
  44. 44. 2017 44 Smart&Soft Agence Digitale 3. Les performances Room Realm Insertion de beaucoup de données 10 991 ms 2 587 ms Insertion d’une ligne 6 ms 4 ms Sélection 3 ms 26 ms Suppression 7 ms 15 ms Mise à jour 4 ms 4 ms
  45. 45. 2017 45 Realm 4. Gestion de la migration • Possibilité de détruire la base de données existante • Possibilité de gérer une migration via l’interface RealmMigration • Migration orientée objet
  46. 46. 2017 46 Room 4. Gestion de la migration • Possibilité de gérer plusieurs migrations via la classe Migration • Migration orientée SQL • Possibilité de faire des tests unitaires sur la migration d’une base de données • Possibilité d’exporter le schéma de base de données au format JSON
  47. 47. 2017 47 Smart&Soft Agence Digitale 5. Autres éléments de comparaison Room Realm Données “observables” RxJava 2 LiveData RxJava 1 jusqu’à Realm 3.x RxJava 2 depuis Realm 4 Méthodes 486 2468 Classes / Interfaces générées 6 8 Poids négligeable ~ 14 MB
  48. 48. Conclusion
  49. 49. Smart&Soft Agence Digitale 2017 49 Liens utiles • https://realm.io/docs/java/latest/ • https://developer.android.com/topic/libraries/architecture/room.h tml
  50. 50. Des questions ?
  51. 51. 92 rue Réaumur - 75 002 - Paris contact@smartnsoft.com www.smartnsoft.com 01 42 12 28 41

×