A Kotlin Multiplatform library for database storage, which aims to support all functionality offered by Room.
Kabin uses drivers from SQLDelight, offering a stable interaction with SQL
on all targets supported by the latter.
[!CAUTION] This library is still under development. Avoid using it in production. You are very welcome to create issues and Pull Requests. Contribution will accelerate development, and pave the way for a production ready solution.
Using Kabin is straight forward. Annotations are identical to those in Room, which means usage is identical too. Here’s how you declare a simple database:
Entity
:
@Entity
data class UserEntity(
@PrimaryKey
val id: Int,
val name: String
)
Dao
:
@Dao
interface UserDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertOrReplace(entity: UserEntity)
}
Database
:
@Database(
entities = [
UserEntity::class
],
version = 1
)
interface SampleDatabase : KabinDatabase {
val userDao: UserDao
}
Kabin will generate code for you and glue everything together.
newInstance
method, to initialize SampleDatabase
:
```kotlin
// Create configuration for every platform, here’s an example for android
val configuration = KabinDatabaseConfiguration(
context = this,
name = “sample-database”
)val sampleDatabase = SampleDatabase::class.newInstance( configuration, migrations = emptyList(), migrationStrategy = KabinMigrationStrategy.DESTRUCTIVE )
For more advanced topics, read [Room](https://developer.android.com/training/data-storage/room) documentation and tutorials, and apply the same logic using Kabin.
## Installation
Latest Kabin version
[![Kabin Release](https://img.shields.io/github/release/tamimattafi/kabin.svg?style=for-the-badge&color=darkgreen)](https://github.com/tamimattafi/kabin/releases)
Add `common` modules to your `sourceSet`:
```kotlin
kotlin {
sourceSets {
val commonMain by getting {
dependencies {
// Kabin
implementation("com.attafitamim.kabin:core:$kabin_version")
}
// Make generated code visible for commonMain
kotlin.srcDir("$buildDir/generated/ksp/metadata/commonMain/kotlin/")
}
}
}
Add ksp
compiler:
plugins {
alias(libs.plugins.kotlin.multiplatform)
alias(libs.plugins.ksp)
}
dependencies {
add("kspCommonMainMetadata", "com.attafitamim.kabin:compiler:$kabin_version")
}
// Workaround for using KSP in common
tasks.withType<KotlinCompile<*>>().configureEach {
if (name != "kspCommonMainKotlinMetadata") {
dependsOn("kspCommonMainKotlinMetadata")
}
}
afterEvaluate {
tasks.filter { task ->
task.name.contains("SourcesJar", true)
}.forEach { task ->
task.dependsOn("kspCommonMainKotlinMetadata")
}
}
Configure ksp
processor to generate more suitable code for you
ksp {
// Use this prefix for fts tables to keep the old room scheme
arg("FTS_TRIGGER_NAME_PREFIX", "room_fts_content_sync")
}
Available keys, with their default values
TABLE_SUFFIX("KabinTable")
ENTITY_MAPPER_SUFFIX("KabinMapper")
DATABASE_SUFFIX("KabinDatabase")
DAO_SUFFIX("KabinDao")
DAO_QUERIES_SUFFIX("KabinQueries")
INDEX_NAME_PREFIX("index")
FTS_TRIGGER_NAME_PREFIX("kabin_fts_content_sync")
BEFORE_UPDATE_TRIGGER_NAME_SUFFIX("BEFORE_UPDATE")
AFTER_UPDATE_TRIGGER_NAME_SUFFIX("AFTER_UPDATE")
BEFORE_DELETE_TRIGGER_NAME_SUFFIX("BEFORE_DELETE")
AFTER_INSERT_TRIGGER_NAME_SUFFIX("AFTER_INSERT")
This list shows Room features, which are already supported by Kabin, or under development
[!NOTE] To accelerate the development of certain features, create issues to increase priority, or upvote existing ones
tableName
indices
inheritSuperIndices
primaryKeys
foreignKeys
ignoredColumns
autoGenerate
@PrimaryKey
on multiple columns@PrimaryKey
on @Embedded
columnsprefix
@Embedded
(@Embedded
inside an @Embedded
)@Embedded
entity inside a class for working with @Relations
)@Embedded
columns as primary keys using @PrimaryKey
name
typeAffinity
index
collate
defaultValue
@Ignore
entity
parentColumns
childColumns
onDelete
onUpdate
deferred
columns
orders
name
unique
entity
parentColumn
entityColumn
associateBy
projection
@Embedded
entitiesvalue
parentColumn
entityColumn
@Junction
table@Junction
entities automatically when inserting classes with @Relation
contentEntity
tokenizerArgs
languageId
notIndexed
prefix
order
suspend
functionsCollection
and Flow
return typesDispatcher.IO
@Dao
@Dao
entity
onConflict
@Embedded
entities including their @Relation
and @Junction
entity
@Embedded
entities including their @Relation
and @Junction
entity
onConflict
@Embedded
entities including their @Relation
and @Junction
[!CAUTION] This annotation is currently treated as @Insert with REPLACE strategy
entity
- Use Upsert logic instead of simple insert with REPLACE strategy
- Upsert single entity, multiple entities as distinct parameters or lists of entities
- Upsert Compound classes with
@Embedded
entities including their@Relation
and@Junction
observedEntities
value
:parameter
?
@Transaction
annotationentities
views
version
exportSchema
autoMigrations
@Database
@Database
[!CAUTION] This annotation can only accept converter
object
that implementapp.cash.sqldelight.ColumnAdapter
value
builtInTypeConverters
enums
(Enums are supported by default)uuid
from
to
spec
Database
classvalue
accepts object
that implements KabinMapper<T>
@Embedded
and @Relation
annotations can be used with @Insert
, @Upsert
, @Delete
and @Update
@Junction
inside a compound is automatically created and inserted as wellcompiler
and processor
logic, make it more flexible and maintainable