• 12 heures
  • Moyenne

Ce cours est visible gratuitement en ligne.

course.header.alt.is_certifying

J'ai tout compris !

Mis à jour le 26/09/2024

Annotez vos interfaces

Maintenant que nous avons des interfaces DAO, nous allons pouvoir utiliser les annotations proposées par Room pour que l’ORM puisse les utiliser et réaliser les bonnes opérations sur la base de données SQLite.

Définir les interfaces avec l’annotation@Dao

La première annotation que nous allons utiliser est l’annotation@Dao. Il s’agit d’un élément essentiel de la bibliothèque Room qui permet de définir des interfaces comme des DAO. Cette annotation est portée directement par l’interface que l’on souhaite définir en tant que Dao.

Si vous utilisez Java :                         

Si vous utilisez Kotlin :                    

@Dao
public interface NoteDao
{
  //...
}
@Dao
public interface AnimalDao
{
  //...
}
@Dao
interface AnimalDao
{
  //…
}
@Dao
interface NoteDao
{
  //…
}

Insérez une donnée avec l’annotation @Insert

Comme vous le savez, le concept de CRUD est au cœur de Room. Pour chacune des opérations, il existe une annotation Room à utiliser. Débutons avec la première opération représentée par le “C” : Create

Créer, c’est en réalité insérer une ligne dans la base de données. L’annotation, portée par une méthode de l’interface, qui permet d’indiquer que ladite méthode est destinée à insérer une ou plusieurs lignes dans la base de données est@Insert.

Dans le cadre de la fonctionnalité développée pour l’application PETiSoin, deux méthodes vont porter cette annotation :insertAnimal etinsertNote.

Si vous utilisez Java :                         

Si vous utilisez Kotlin :                    

@Dao
public interface AnimalDao
{
  @Insert
  void insertAnimal(Animal animal);
  //...
}
@Dao
public interface NoteDao
{
  @Insert
  void insertNote(Note note);
  //...
}
@Dao
interface AnimalDao
{
  @Insert
  suspend fun insertAnimal(animal: Animal)
  //…
}
@Dao
interface NoteDao
{
  @Insert
  suspend fun insertNote(note: Note)
  //…
}

En SQL, lors de l’insertion d’une ligne dans la base de données relationnelle, il peut se produire des conflits. C’est par exemple le cas lorsque l’on tente d’insérer une ligne dont la clé primaire est déjà présente dans la base de données. Dans Room si un tel cas se produit, l’insertion va simplement échouer par défaut.

Room offre alors la possibilité de personnaliser son comportement face à de telles situations. En cas de conflit lors de l’insertion d’une ligne dans la base de données, l’attribut onConflict, de l’annotation  @Insertqui permet de personnaliser le comportement de Room. Les valeurs possibles pour cet attribut et le comportement de Room sont détaillés dans ce tableau.

Valeur                              

Comportement en cas de conflit

OnConflictStrategy.ABORT

L’insertion est annulée et l’ensemble de la transaction est annulé.

OnConflictStrategy.IGNORE

L’insertion est annulée mais le reste de la transaction se poursuit.

OnConflictStrategy.REPLACE

L’insertion remplace la ligne avec laquelle elle est en conflit.

 Illustrons l’utilisation de la stratégie OnConflictStrategy.REPLACEsur les interfaces  AnimalDaoetNoteDao.

Si vous utilisez Java :                         

Si vous utilisez Kotlin :                    

@Dao
public interface AnimalDao
{
  @Insert(onConflict = OnConflictStrategy.REPLACE)
  void insertAnimal(Animal animal);
  //...
}
@Dao
public interface NoteDao
{
  @Insert(onConflict = OnConflictStrategy.REPLACE)
  void insertNote(Note note);
  //...
}
@Dao
interface AnimalDao
{
  @Insert(onConflict = OnConflictStrategy.REPLACE)
  suspend fun insertAnimal(animal: Animal)
  //…
}
@Dao
interface NoteDao
{
  @Insert(onConflict = OnConflictStrategy.REPLACE)
  suspend fun insertNote(note: Note)
  //…
}

Sélectionnez une donnée avec l’annotation@Query

Continuons l’exploration des lettres qui composent le mot CRUD avec la lettre “R” : Read

Lire, c’est en réalité sélectionner une ou plusieurs lignes de la base de données répondant à un ou plusieurs critères que vous pouvez définir en tant que développeur. Pour sélectionner des lignes dans la base de données, l’annotation à utiliser est@Query.

L’annotation  @Read  n’existe pas ? 

Effectivement, l’annotation @Read, bien que logique, n’existe pas. En réalité, si l’on doit utiliser l’annotation@Queryc’est que pour sélectionner les lignes qui vous intéressent, il convient d’écrire des requêtes SQL en tant qu’unique attribut de l’annotation.

Dans le cadre de la fonctionnalité développée pour l’application PETiSoin, plusieurs méthodes vont porter cette annotation :getAnimalById,  getAllAnimals,  getNoteByIdet  getAllNotesByAnimalId.

Si vous utilisez Java :                         

Si vous utilisez Kotlin :                    

@Dao
public interface AnimalDao
{
  //...
  @Query("SELECT * FROM Animal WHERE id = :id")
  Animal getAnimalById(int id);
  @Query("SELECT * FROM Animal")
  LiveData<List<Animal>> getAllAnimals();
}

@Dao
public interface NoteDao
{
  //...
  @Query("SELECT * FROM Note WHERE id = :id")
  Note getNoteById(int id);
  @Query("SELECT * FROM Note WHERE animalId = :id")
  LiveData<List<Note>> getAllNotesByAnimalId(int id);
}
@Dao
interface AnimalDao
{
  //…
  @Query("SELECT * FROM animal")
  fun getAllAnimals(): Flow<List<Animal>>
  @Query("SELECT * FROM animal WHERE id = :id")
  suspend fun getAnimalById(id: Int): Animal
}
@Dao
interface NoteDao
{
  //…
  @Query("SELECT * FROM Note WHERE id = :id")
  suspend fun getNoteById(id: Int): Note
  @Query("SELECT * FROM Note WHERE animalId = :id")
  fun getAllNotesByAnimalId(id: Int): Flow<List<Note>>
}

Mettez à jour une donnée avec l’annotation@Update

Continuons l’exploration des lettres qui composent le mot CRUD avec la lettre “U” : Update

Mettre à jour, c’est en réalité modifier une ligne qui est déjà présente dans la base de données. Notez que dans ce cas la clé primaire associée à la ligne ne change pas. Si cette clé était modifiée, cela reviendrait à créer une nouvelle ligne. La méthode de l’interface porte l’annotation qui se nomme @Update. Cette dernière est destinée à supprimer une ou plusieurs lignes dans la base de données.

Dans le cadre de la fonctionnalité développée pour l’application PETiSoin, deux méthodes vont porter cette annotation :updateAnimaletupdateNote .

Si vous utilisez Java :                         

Si vous utilisez Kotlin :                    

@Dao
public interface AnimalDao
{
  @Update
  void updateAnimal(Animal animal);
  //...
}
@Dao
public interface NoteDao
{
  @Update
  void updatetNote(Note note);
  //...
}
@Dao
interface AnimalDao
{
  @Update
  suspend fun updateAnimal(animal: Animal)
  //…
}
@Dao
interface NoteDao
{
  @Update
  suspend fun updateNote(note: Note)
  //…
}

À l’image des insertions de données, la mise à jour d’une ligne dans la base de données relationnelle peut entraîner des conflits. Dans Room, si un tel cas se produit, la mise à jour va simplement échouer par défaut. L’attributonConflictpermet alors de gérer ce genre de situation. Les valeurs possibles pour cet attribut et le comportement de Room sont détaillés dans ce tableau. 

Valeur

Comportement en cas de conflit

OnConflictStrategy.ABORT

La mise à jour est annulée et l’ensemble de la transaction est annulé.

OnConflictStrategy.IGNORE

La mise à jour est annulée mais le reste de la transaction se poursuit.

OnConflictStrategy.REPLACE

La mise à jour remplace la ligne avec laquelle elle est en conflit.

Illustrons l’utilisation de la stratégieOnConflictStrategy.REPLACEsur les interfacesAnimalDao  et NoteDao.

Si vous utilisez Java :                         

Si vous utilisez Kotlin :                    

@Dao
public interface AnimalDao
{
  @Update(onConflict = OnConflictStrategy.REPLACE)
  void updateAnimal(Animal animal);
  //...
}
@Dao
public interface NoteDao
{
  @Update(onConflict = OnConflictStrategy.REPLACE)
  void updateNote(Note note);
  //...
}
@Dao
interface AnimalDao
{
  @Update(onConflict = OnConflictStrategy.REPLACE)
  suspend fun updateAnimal(animal: Animal)
  //…
}
@Dao
interface NoteDao
{
  @Update(onConflict = OnConflictStrategy.REPLACE)
  suspend fun updateNote(note: Note)
  //…
}

 Insérez ou mettez à jour une donnée avec l’annotation  @Upsert 

Les annotations que nous avons vues jusqu’à maintenant couvrent des scénarios simples et notamment l’insertion et la mise à jour. Mais elles ne répondent pas au scénario suivant : insérer ou mettre à jour. C’est pour répondre à ce besoin que l’annotation@Upserta été introduite dans la version 2.5.0 de Room. L'objectif principal de cette annotation est de combiner les opérations d'insertion et de mise à jour en une seule instruction, simplifiant ainsi le code et améliorant l'efficacité des opérations sur la base de données.

Utiliser l’annotation@Insertavec la stratégie de conflitOnConflictStrategy.REPLACEne permet-elle pas de répondre à ce besoin ? 

Sur le papier effectivement, mais dans les faits, c’est un peu plus subtil que ça. Lors de la requête d’insertion, s’il y a un conflit, Room ne va pas réellement mettre à jour la ou les lignes concernées. Il va en réalité les supprimer de la base de données pour insérer les nouvelles. Cette façon de faire peut être à l’origine d’effets de bord. Par exemple, si la ligne supprimée a des informations qui ne sont pas fournies par la nouvelle insertion (par exemple, des colonnes non nulles ou des champs non fournis dans l'objet inséré), ces informations seront perdues.

C’est pour répondre à ce besoin que Room permet d’utiliser l’annotation@Upsert. Illustrons son utilisation sur les interfacesAnimalDao  et NoteDao.

Si vous utilisez Java :                         

Si vous utilisez Kotlin :                    

@Dao
public interface AnimalDao
{
  @Upsert
  void insertAnimal(Animal animal);
  //...
}
@Dao
public interface NoteDao
{
  @Upsert
  void insertNote(Note note);
  //...
}
@Dao
interface AnimalDao
{
  @Upsert
  suspend fun insertAnimal(animal: Animal)
  //…
}
@Dao
interface NoteDao
{
  @Upsert
  suspend fun insertNote(note: Note)
  //…
}

Supprimez une donnée avec l’annotation@Delete 

Après le “U” de CRUD, attaquons nous maintenant à la dernière lettre “D” : Delete.  

Dans le cadre d’une base de données relationnelle, supprimer, c’est supprimer une ligne dans la base de données. La méthode de l’interface porte l’annotation qui se nomme@Delete. Cette dernière est destinée à supprimer une ou plusieurs lignes dans la base de données. 

Dans le cadre de la fonctionnalité développée pour l’application PETiSoin, deux méthodes vont porter cette annotation :deleteAnimal etdeleteNote.

Si vous utilisez Java :                         

Si vous utilisez Kotlin :                    

public interface AnimalDao
{
  //...
  @Delete
  void deleteAnimal(Animal animal);
  //...
}
public interface NoteDao
{
  //...
  @Delete
  void deleteNote(Note note);
  //...
}
interface AnimalDao
{
  //…
  @Delete
  suspend fun deleteAnimal(animal: Animal)
  //…
}
interface NoteDao
{
  //…
  @Delete
  suspend fun deleteNote(note: Note)
  //…
}

Voici une vidéo qui récapitule les principales étapes pour intégrer et annoter des DAO.

À vous de jouer !

Contexte

Vous devez continuer l’implémentation technique de la rubrique “Santé” de l’application PETiSoin, en vous attaquant aux DAOs.

Dans le projet, disponible sur GitHub (Java ou Kotlin), les interfaces DAOAnimalDao et VaccineDaoont déjà été créées mais elles ne portent pas les annotations Room.

Consignes

  1. Dans le packagecom.openclassRooms.Room.data.dao, complétez le code des DAOsAnimalDao et VaccineDaoavec les annotations Room :

    1. @Dao

    2. @Query 

    3. @Upsert

    4. @Delete

Livrables

Vous pouvez dupliquer le projet GitHub pour modifier le code source du projet et fournir un projet qui compile.

En résumé

  • L’annotation@Daodésigne une interface comme étant un DAO (Data Access Object).

  • L’annotation@Insertindique qu’une méthode du DAO est une méthode d’insertion.

  • L’annotation@Querypermet d’écrire des requêtes SQL dont des requêtes de sélection.

  • L’annotation@Updateindique qu’une méthode du DAO est une méthode de mise à jour.

  • L’annotation@Upsertindique qu’une méthode du DAO est une méthode d’insertion ou de mise à jour.

  • L’annotation@Deleteindique qu’une méthode du DAO est une méthode de suppression.

Vous avez défini la couche DAO permettant d’exposer l’ensemble des interactions possibles avec votre base de données grâce aux différentes annotations de Room. Nous pouvons maintenant finaliser la création de la base de données de l’application PETiSoin.

Exemple de certificat de réussite
Exemple de certificat de réussite