Room: kernconcepten, Entity, DAO en werken met databases

Auteur: IT Sectr Gepubliceerd: 2026-05-04 Leestijd: 8 min

Room is een bibliotheek voor het werken met SQLite in Android, onderdeel van Jetpack. Het biedt een abstractielaag bovenop ruwe SQLite en automatiseert het aanmaken van tabellen, het uitvoeren van query's en het converteren van gegevens naar Kotlin- en Java-objecten. Volgens Android Developers compileert Room SQL-query's tijdens de buildfase en controleert het de juistheid van de syntax en de relaties tussen Entity en tabellen.

Belangrijkste punten

  • Room — Jetpack ORM-bibliotheek voor SQLite in Android-apps.
  • Entity — klasse geannoteerd met @Entity, elke instantie komt overeen met een rij in de tabel.
  • DAO — Data Access Object met geannoteerde methoden voor SQL-query's.
  • Database — abstracte klasse die RoomDatabase uitbreidt en Entity met DAO verbindt.
  • Migratie — mechanisme voor veilige schema-wijzigingen zonder verlies van gebruikersgegevens.

Wat is Room en waarom heb je het nodig

Room is een persistentiebibliotheek uit Android Jetpack die object-relationele mapping biedt voor SQLite. Room lost drie hoofdproblemen van ruwe SQLite op: het schrijven van veel boilerplate-code voor het aanmaken van tabellen, het ontbreken van SQL-querycontrole tijdens compilatie en handmatige conversie van Cursor naar objecten.

De bibliotheek gebruikt een annotatiecompiler (kapt of KSP) die tijdens de buildfase de implementatie van abstracte RoomDatabase- en DAO-klassen genereert. Dit garandeert dat syntaxfouten in SQL en type-mismatches worden gedetecteerd voordat de app wordt gestart, niet in runtime na publicatie in Google Play.

Volgens Google I/O 2023 wordt Room gebruikt in 68% van de Android-apps die met lokale gegevens werken. Het is de standaard voor gegevensopslag op het apparaat, aanbevolen door Google voor alle nieuwe projecten — in plaats van verouderde SQLiteOpenHelper en ContentProvider.

Implementeer Room in projecten waar lokale caching van servergegevens, offline modus of opslag van gestructureerde gebruikersgegevens met complexe SQL-query's nodig is.

Room maakt deel uit van Android Jetpack en wordt officieel aanbevolen door Google voor alle nieuwe projecten die met lokale gegevens werken. In tegenstelling tot Realm of ObjectBox gebruikt Room native SQLite, wat compatibiliteit garandeert met alle externe tools voor databasewerk — van DB Browser tot DataGrip. De ontwikkelaar kan het .db-bestand van de app openen en direct SQL-query's uitvoeren, wat debugging en gegevensanalyse tijdens de ontwikkeling vereenvoudigt.

Entity en annotaties in Room

Entity is een gegevensklasse geannoteerd met @Entity, die Room omzet in een databasetabel. Elk veld van de klasse wordt een kolom in de tabel, elke instantie wordt een rij. Room gebruikt reflectie voor toegang tot velden, daarom is de @PrimaryKey-annotatie vereist voor een verplichte identifier.

Basisannotaties

De @Entity-annotatie geeft Room aan dat de klasse een tabel is. De parameter tableName bepaalt de tabelnaam als deze verschilt van de klassenaam. @PrimaryKey definieert de primaire sleutel met automatische generatie 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 bepaalt de kolomnaam in de tabel als deze verschilt van de Kotlin-veldnaam. @Ignore sluit het veld uit van de tabel — het wordt niet opgeslagen in de database. @ForeignKey beschrijft externe sleutels voor relaties tussen tabellen met cascade-operaties bij verwijderen of bijwerken.

Room ondersteunt geneste objecten via de @Embedded-annotatie. Velden van de geneste klasse worden uitgevouwen naar kolommen van de parent-tabel met een prefix om naamconflicten te voorkomen. Bijvoorbeeld, een Address-klasse met velden city en street, ingebed in User, maakt kolommen address_city en address_street aan in de users-tabel, waardoor aparte tabellen voor eenvoudige waarde-objecten niet nodig zijn.

Conversietypen

Room ondersteunt alleen primitieve typen en hun wrappers. Voor het opslaan van lijsten, Date of aangepaste typen wordt @TypeConverter gebruikt — statische conversiemethoden tussen een aangepast type en een SQLite-primitief, bijvoorbeeld tussen List en een JSON-string.

DAO en SQL-query's

DAO (Data Access Object) is een interface of abstracte klasse geannoteerd met @Dao, die methoden bevat voor gegevenstoegang. Elke methode is geannoteerd met een SQL-bewerking: @Insert, @Update, @Delete of @Query met een expliciete SQL-query.

@Query met controle tijdens compilatie

De @Query-annotatie accepteert een SQL-string die door Room tijdens compilatie wordt gecontroleerd op syntaxcorrectheid en overeenkomst van kolomnamen met Entity-velden. Room ondersteunt geparametriseerde query's via de syntax :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 ondersteunt OnConflictStrategy-strategieën voor het afhandelen van conflicten bij het invoegen van dubbele records. Flow als retourtype zorgt voor reactieve UI-updates bij elke gegevenswijziging in de tabel — het abonnement wordt automatisch herstart bij elke INSERT, UPDATE of DELETE.

@Transaction voor complexe bewerkingen

De @Transaction-annotatie garandeert atomische uitvoering van meerdere bewerkingen in één transactieblok. Room vergrendelt de database tijdens uitvoering, waardoor race-conditions bij gelijktijdige toegang vanuit meerdere threads worden voorkomen.

Database en schema-migraties

RoomDatabase is een abstracte klasse die Entity en DAO verenigt in één toegangspunt tot de database. Het wordt gemaakt via Room.databaseBuilder met opgave van de schemaversie en een lijst van Entity-klassen. Het wordt aanbevolen om de database-instantie als singleton te maken via een lazy-delegate om meerdere verbindingen te voorkomen.

Migraties

Migratie in Room is een Migration-klasse die een SQL-script beschrijft voor de overgang van een oude naar een nieuwe schemaversie. Als er geen migratie wordt verstrekt bij schema-wijziging, gooit Room een IllegalStateException. Dit beschermt tegen onbedoeld verlies van gebruikersgegevens bij het updaten van de app.

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()

Voor ontwikkeling kan fallbackToDestructiveMigration worden gebruikt, die de oude database verwijdert en een nieuwe maakt bij versie-mismatch. Deze modus is alleen bedoeld voor debugging — in productiereleases moeten migraties worden geschreven.

Voor het testen van de database biedt Room een speciale klasse Room.inMemoryTestBuilder die een database in RAM-geheugen creëert zonder opslag op schijf. Na afloop van elke test wordt de database automatisch vernietigd, wat volledige isolatie van testscenario's garandeert. In combinatie met de bibliotheek android-arch-core-testing kan de ontwikkelaar de levenscyclus van de database beheren en de juistheid van migraties controleren zonder handmatig de status te hoeven wissen.

De prestaties van Room zijn direct afhankelijk van de structuur van query's en indexen. Voor analyse van trage query's biedt Room de vlag enableQueryCallback, die alle SQL-query's met uitvoeringstijd logt. De ontwikkelaar kan dit logboek gebruiken om query's te vinden die langer dan 100 milliseconden duren en deze te optimaliseren door samengestelde indexen toe te voegen via de @Index-annotatie in @Entity of door subquery's te herschrijven naar directe JOIN-verbindingen met @Relation.

Room ondersteunt ook databaseversleuteling via SQLCipher. Het aansluiten van de bibliotheek net.zetetic:android-database-sqlcipher en het gebruik van SupportFactory in plaats van de standaard zorgt voor transparante versleuteling van alle gegevens op schijf zonder wijziging van DAO-query's en Entity-structuur. Dit is noodzakelijk voor apps die met persoonlijke gebruikersgegevens werken en voldoet aan de vereisten van GDPR en de Russische 152-FZ-wet over bescherming van persoonsgegevens. Het versleutelingswachtwoord kan worden opgeslagen in Android Keystore ter bescherming tegen extractie via tools op geroote apparaten.

Room met Kotlin Coroutines en Flow

Room ondersteunt vanaf versie 2.1 native Kotlin Coroutines. DAO-methoden kunnen suspend-functies zijn die query's op de achtergrond uitvoeren zonder de hoofdthread te blokkeren. Room beheert automatisch de dispatchers en gebruikt Dispatchers.IO voor lees- en schrijfquery's.

Voor reactieve query's retourneert Room Flow — een koude gegevensstroom die een nieuwe waarde uitzendt bij elke wijziging van de betreffende tabel. ViewModel abonneert zich op Flow via stateIn of collect, wat zorgt voor automatische UI-updates zonder handmatige melding van de adapter.

Room ondersteunt ook Paging 3 via een speciale PagingSource-implementatie die gegevens paginagewijs uit SQLite laadt. Dit is efficiënt voor grote lijsten met duizenden records: Paging 3 laadt alleen de zichtbare rijen op het scherm en werkt ze automatisch bij bij wijzigingen in de database.

Gebruik Paging 3 met Room bij het weergeven van een nieuwsfeed, operationeel logboek of productlijst met offline toegang en oneindig scrollen.

Veelgestelde vragen

Wat is het verschil tussen Room en SQLiteOpenHelper?

Room automatiseert het aanmaken van tabellen, conversie van Cursor naar objecten en SQL-controle tijdens compilatie. SQLiteOpenHelper vereist handmatig schema-schrijven, Cursor-verwerking en heeft geen querycontrole voordat de app wordt gestart, wat het risico op fouten vergroot.

Moet ik voor elke schema-wijziging migraties schrijven?

Ja, bij wijziging van Entity (toevoegen/verwijderen van veld, typewijziging) is een migratie vereist. Zonder migratie gooit Room een IllegalStateException bij het opstarten. Voor ontwikkeling kan fallbackToDestructiveMigration worden ingeschakeld, maar in de release zijn correcte migratiescripts verplicht.

Ondersteunt Room relaties tussen tabellen?

Room ondersteunt @ForeignKey voor cascade-operaties en @Relation voor geneste objecten. Voor complexe JOIN-query's wordt de @Transaction-annotatie gebruikt met @Query die POJO retourneert met geneste entiteiten via @Embedded en @Relation.

Kan ik Room gebruiken met Java zonder Kotlin?

Ja, Room is volledig compatibel met Java. In plaats van suspend-functies worden LiveData of RxJava Observable gebruikt, in plaats van Flow — LiveData. Room met Java ondersteunt allezelfde annotaties, maar vereist meer boilerplate-code voor asynchrone bewerkingen.

Hoe werkt databaseversleuteling in Room?

Room ondersteunt versleuteling via SQLCipher van Zetetic. Gebruik in plaats van Room.databaseBuilder de SupportFactory uit de bibliotheek net.zetetic:android-database-sqlcipher en geef het versleutelingswachtwoord door. Alle gegevens op schijf worden transparant versleuteld voor DAO-query's.

Samenvatting

  • Room — Jetpack ORM-bibliotheek voor SQLite met SQL-controle tijdens compilatie.
  • @Entity beschrijft de tabel, @PrimaryKey — de identifier, @ColumnInfo — de kolomnaam.
  • @Dao bevat methoden met @Query, @Insert, @Update en @Delete voor gegevenstoegang.
  • RoomDatabase verenigt Entity en DAO, gemaakt via Room.databaseBuilder.
  • Migraties (Migration) beschrijven SQL-scripts voor schema-wijzigingen zonder gegevensverlies.
  • Room ondersteunt native Kotlin Coroutines (suspend) en Flow voor reactieve UI-updates.
  • Gebruik Paging 3 met Room via PagingSource voor paginagewijze laad van grote lijsten.

We ontwikkelen een mobiele applicatie turnkey

IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.

Bespreek het project

Lees ook