
Multiplatform database library simplifies storage by emulating Room's functionality, using SQLDelight drivers for SQL interactions. Offers annotations for seamless entity, DAO, and database creation.
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.
Room already has Kotlin Multiplatform support and is stable. Please consider using it instead.
Kabin will be maintained less often and more like a pet project. 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:// 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 documentation and tutorials, and apply the same logic using Kabin.
Latest Kabin version
Add common modules to your sourceSet:
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
@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
objectthat 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 maintainableA 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.
Room already has Kotlin Multiplatform support and is stable. Please consider using it instead.
Kabin will be maintained less often and more like a pet project. 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:// 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 documentation and tutorials, and apply the same logic using Kabin.
Latest Kabin version
Add common modules to your sourceSet:
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
@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
objectthat 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