Room : concepts clés, Entity, DAO et travail avec les bases de données

Auteur : IT Sectr Publié le : 2026-05-04 Temps de lecture : 8 min

Room est une bibliothèque pour travailler avec SQLite dans Android, faisant partie de Jetpack. Elle fournit une couche d’abstraction au-dessus du SQLite brut, automatisant la création de tables, l’exécution de requêtes et la conversion de données en objets Kotlin et Java. Selon Android Developers, Room compile les requêtes SQL au moment de la construction, vérifiant la correction de la syntaxe et les relations entre Entity et les tables.

Points essentiels

  • Room est une bibliothèque ORM de Jetpack pour travailler avec SQLite dans les applications Android.
  • Entity est une classe annotée avec @Entity, chaque instance correspond à une ligne dans une table.
  • DAO est un objet d’accès aux données avec des méthodes annotées pour les requêtes SQL.
  • Database est une classe abstraite étendant RoomDatabase, liant Entity et DAO.
  • Migration est un mécanisme pour modifier en toute sécurité le schéma de la base de données sans perdre les données utilisateur.

Qu’est-ce que Room et pourquoi en a-t-on besoin

Room est une bibliothèque de persistance d’Android Jetpack qui fournit un mapping objet-relationnel pour SQLite. Room résout trois problèmes principaux du SQLite brut : l’écriture de grandes quantités de code boilerplate pour créer des tables, l’absence de vérification des requêtes SQL au moment de la compilation et la conversion manuelle de Cursor en objets.

La bibliothèque utilise un processeur d’annotations (kapt ou KSP) qui génère l’implémentation des classes abstraites RoomDatabase et DAO au moment de la construction. Cela garantit que les erreurs de syntaxe dans SQL et les incompatibilités de types sont découvertes avant l’exécution de l’application, plutôt qu’au moment de l’exécution après la publication sur Google Play.

Selon Google I/O 2023, Room est utilisé dans 68% des applications Android qui travaillent avec des données locales. C’est la norme pour le stockage de données sur l’appareil, recommandée par Google pour tous les nouveaux projets — au lieu des obsolètes SQLiteOpenHelper et ContentProvider.

Intégrez Room dans les projets nécessitant une mise en cache locale des données du serveur, un mode hors ligne ou un stockage de données utilisateur structurées avec la possibilité d’exécuter des requêtes SQL complexes.

Room fait partie d’Android Jetpack et est officiellement recommandé par Google pour tous les nouveaux projets travaillant avec des données locales. Contrairement à Realm ou ObjectBox, Room utilise SQLite natif, garantissant la compatibilité avec tout outil de base de données tiers — de DB Browser à DataGrip. Les développeurs peuvent ouvrir le fichier .db de l’application et exécuter des requêtes SQL directement, ce qui simplifie le débogage et l’analyse des données pendant le développement.

Entity et annotations dans Room

Entity est une classe de données annotée avec @Entity que Room transforme en table de base de données. Chaque champ de la classe devient une colonne de la table, et chaque instance devient une ligne. Room utilise la réflexion pour accéder aux champs, donc l’annotation @PrimaryKey est requise pour un identifiant obligatoire.

Annotations principales

L’annotation @Entity indique à Room que la classe est une table. Le paramètre tableName définit le nom de la table s’il diffère du nom de la classe. @PrimaryKey définit la clé primaire avec prise en charge de l’auto-génération via autoGenerate = true.

kotlin
@Entity(tableName = "users")
data class User(
    @PrimaryKey(autoGenerate = true)
    val id: Int = 0,
    @ColumnInfo(name = "full_name")
    val name: String,
    @Ignore
    val tempData: String?
)

@ColumnInfo spécifie le nom de la colonne dans la table s’il diffère du nom du champ Kotlin. @Ignore exclut un champ de la table — il ne sera pas enregistré dans la base de données. @ForeignKey décrit les clés étrangères pour les relations entre tables avec des opérations en cascade lors de la suppression ou de la mise à jour.

Room prend en charge les objets imbriqués via l’annotation @Embedded. Les champs de la classe imbriquée sont développés en colonnes de la table parente avec un préfixe pour éviter les conflits de noms. Par exemple, une classe Address avec les champs city et street intégrée dans User créera les colonnes address_city et address_street dans la table users, éliminant le besoin de tables séparées pour les objets de valeur simples.

Convertisseurs de type

Room ne prend en charge que les types primitifs et leurs wrappers. Pour stocker des listes, Date ou des types personnalisés, utilisez @TypeConverter — des méthodes statiques pour convertir entre un type personnalisé et un primitif SQLite, par exemple, entre List et une chaîne JSON.

DAO et requêtes SQL

DAO (Data Access Object) est une interface ou classe abstraite annotée avec @Dao contenant des méthodes pour l’accès aux données. Chaque méthode est annotée avec une opération SQL : @Insert, @Update, @Delete ou @Query avec une requête SQL explicite.

@Query avec vérification au moment de la compilation

L’annotation @Query prend une chaîne SQL que Room vérifie au moment de la compilation pour la correction de la syntaxe et la correspondance des noms de colonnes avec les champs Entity. Room prend en charge les requêtes paramétrées via la syntaxe :paramName.

kotlin
@Dao
interface UserDao {
    @Query("SELECT * FROM users WHERE id = :userId")
    suspend fun getUserById(userId: Int): User?

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertUser(user: User)

    @Query("SELECT * FROM users ORDER BY name ASC")
    fun getAllUsers(): Flow<List<User>>
}

@Insert prend en charge les stratégies OnConflictStrategy pour gérer les conflits lors de l’insertion d’enregistrements en double. Flow comme type de retour fournit des mises à jour réactives de l’interface utilisateur à chaque modification des données dans la table — l’abonnement redémarre automatiquement à chaque INSERT, UPDATE ou DELETE.

@Transaction pour les opérations complexes

L’annotation @Transaction garantit l’exécution atomique de plusieurs opérations dans un seul bloc transactionnel. Room verrouille la base de données pendant l’exécution, empêchant les conditions de course lors d’un accès concurrent depuis plusieurs threads.

Database et migrations de schéma

RoomDatabase est une classe abstraite qui combine Entity et DAO en un point d’accès unique à la base de données. Elle est créée via Room.databaseBuilder avec la version du schéma et une liste de classes Entity. L’instance de la base de données doit être créée en tant que singleton via un délégué lazy pour éviter les connexions multiples.

Migrations

Une migration dans Room est une classe Migration qui décrit un script SQL pour la transition d’une ancienne version de schéma vers une nouvelle. Si une migration n’est pas fournie lors du changement de schéma, Room lance une IllegalStateException. Cela protège contre la perte accidentelle de données utilisateur lors de la mise à jour de l’application.

kotlin
val migration_1_2 = object : Migration(1, 2) {
    override fun migrate(db: SupportSQLiteDatabase) {
        db.execSQL("ALTER TABLE users ADD COLUMN age INTEGER NOT NULL DEFAULT 0")
    }
}

val db = Room.databaseBuilder(
    getApplication(),
    AppDatabase::class.java,
    "app_database"
).addMigrations(migration_1_2)
 .build()

Pour le développement, vous pouvez utiliser fallbackToDestructiveMigration, qui supprime l’ancienne base de données et en crée une nouvelle en cas d’incompatibilité de version. Ce mode est destiné uniquement au débogage — les versions de production doivent inclure des migrations appropriées.

Pour tester la base de données, Room fournit une classe spéciale Room.inMemoryTestBuilder qui crée une base de données en mémoire sans sauvegarder sur le disque. Après chaque test, la base de données est automatiquement détruite, garantissant un isolement complet des scénarios de test. Combiné avec la bibliothèque android-arch-core-testing, les développeurs peuvent gérer le cycle de vie de la base de données et vérifier l’exactitude des migrations sans avoir à nettoyer manuellement l’état.

Les performances de Room dépendent directement de la structure des requêtes et des index. Pour analyser les requêtes lentes, Room fournit le flag enableQueryCallback, qui enregistre toutes les requêtes SQL avec le temps d’exécution. Les développeurs peuvent utiliser ce journal pour trouver les requêtes qui prennent plus de 100 millisecondes et les optimiser en ajoutant des index composites via l’annotation @Index dans @Entity ou en réécrivant les sous-requêtes en opérations JOIN directes avec @Relation.

Room prend également en charge le chiffrement de base de données via SQLCipher. L’ajout de la bibliothèque net.zetetic:android-database-sqlcipher et l’utilisation de SupportFactory au lieu de l’implémentation standard fournit un chiffrement transparent de toutes les données sur le disque sans modifier les requêtes DAO ni la structure Entity. Ceci est nécessaire pour les applications traitant des données personnelles des utilisateurs et est conforme au RGPD et à la loi fédérale russe 152-FZ sur la protection des données personnelles. Le mot de passe de chiffrement peut être stocké dans Android Keystore pour le protéger contre l’extraction via des outils sur les appareils rootés.

Room avec Kotlin Coroutines et Flow

Room prend nativement en charge Kotlin Coroutines à partir de la version 2.1. Les méthodes DAO peuvent être des fonctions suspend qui exécutent des requêtes dans un thread d’arrière-plan sans bloquer le thread principal. Room gère automatiquement les dispatchers, en utilisant Dispatchers.IO pour les requêtes de lecture et d’écriture.

Pour les requêtes réactives, Room renvoie un Flow — un flux de données froid qui émet une nouvelle valeur à chaque modification de la table concernée. ViewModel s’abonne au Flow via stateIn ou collect, fournissant des mises à jour automatiques de l’interface utilisateur sans notification manuelle de l’adaptateur.

Room prend également en charge Paging 3 via une implémentation spéciale de PagingSource qui charge les données page par page à partir de SQLite. C’est efficace pour les grandes listes contenant des milliers d’enregistrements : Paging 3 charge uniquement les lignes visibles à l’écran et les met automatiquement à jour lors des modifications de la base de données.

Utilisez Paging 3 avec Room pour afficher des flux d’actualités, des journaux d’opérations ou des listes de produits avec accès hors ligne et défilement infini.

Foire aux questions

Quelle est la différence entre Room et SQLiteOpenHelper ?

Room automatise la création de tables, la conversion Cursor en objets et la vérification SQL au moment de la compilation. SQLiteOpenHelper nécessite d’écrire le schéma manuellement, de gérer Cursor et n’a pas de vérification des requêtes avant l’exécution de l’application, ce qui augmente le risque d’erreurs.

Dois-je écrire des migrations pour chaque changement de schéma ?

Oui, lors de la modification d’une Entity (ajout/suppression d’un champ, changement de type), une migration est nécessaire. Sans elle, Room lance une IllegalStateException au démarrage. Pour le développement, vous pouvez activer fallbackToDestructiveMigration, mais les versions de production nécessitent des scripts de migration corrects.

Room prend-il en charge les relations entre tables ?

Room prend en charge @ForeignKey pour les opérations en cascade et @Relation pour les objets imbriqués. Pour les requêtes JOIN complexes, utilisez l’annotation @Transaction avec @Query retournant un POJO avec des entités imbriquées via @Embedded et @Relation.

Puis-je utiliser Room avec Java sans Kotlin ?

Oui, Room est entièrement compatible avec Java. Au lieu de fonctions suspend, utilisez LiveData ou RxJava Observable ; au lieu de Flow, utilisez LiveData. Room avec Java prend en charge toutes les mêmes annotations, mais nécessite plus de code boilerplate pour les opérations asynchrones.

Comment fonctionne le chiffrement de la base de données Room ?

Room prend en charge le chiffrement via SQLCipher de Zetetic. Au lieu de Room.databaseBuilder, utilisez SupportFactory de la bibliothèque net.zetetic:android-database-sqlcipher, en passant le mot de passe de chiffrement. Toutes les données sur le disque seront chiffrées de manière transparente pour les requêtes DAO.

Résumé

  • Room est une bibliothèque ORM Jetpack pour SQLite avec vérification SQL au moment de la compilation.
  • @Entity décrit la table, @PrimaryKey est l’identifiant, @ColumnInfo est le nom de la colonne.
  • @Dao contient des méthodes avec @Query, @Insert, @Update et @Delete pour l’accès aux données.
  • RoomDatabase combine Entity et DAO, créée via Room.databaseBuilder.
  • Les migrations (Migration) décrivent des scripts SQL pour les changements de schéma sans perte de données.
  • Room prend nativement en charge Kotlin Coroutines (suspend) et Flow pour les mises à jour réactives de l’interface utilisateur.
  • Pour les grandes listes, utilisez Paging 3 avec Room via PagingSource pour le chargement paginé.

Nous développerons une application mobile clé en main

IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.

Discuter du projet

Lisez aussi