Writes

August 23, 2026 ยท View on GitHub

Use the generated ModelAdapter inside writableTransaction. Operations are suspend.

db.writableTransaction {
    val saved = userAdapter.save(User(name = "Ada"))
    userAdapter.insert(User(name = "Grace"))
    userAdapter.update(saved.copy(name = "Ada Lovelace"))
    userAdapter.delete(saved)
}
MethodSQL-ish behavior
save / saveAllINSERT OR REPLACE
insert / insertAllINSERT
update / updateAllUPDATE by primary key
delete / deleteAllDELETE by primary key

Autoincrement ids are filled in on the returned model.

Batch:

db.writableTransaction {
    userAdapter.saveAll(listOf(User(name = "A"), User(name = "B")))
}

Query writes

db.writableTransaction {
    (userAdapter.update()
        set (User.name eq "Grace")
        where (User.name eq "Ada")).execute()

    (userAdapter.delete() where (User.name eq "Grace")).execute()

    userAdapter.insert(
        User.name.eq("Lin"),
    ).execute()
}

Scopes

db.writableTransaction { /* reads + writes */ }
db.readableTransaction { /* reads only */ }

Both run on the database transaction dispatcher. Prefer a transaction over many ad-hoc writes.

Async callbacks

For Android callbacks instead of suspend:

db.beginTransactionAsync {
    userAdapter.save(User(name = "Ada"))
}.execute(
    success = { _, user -> },
    error = { _, throwable -> },
)

enqueue queues without blocking. cancel() is a no-op after the work has started.

Exists

db.writableTransaction {
    userAdapter.exists(user)
}