一个轻量、无注解的 Android SQLite ORM,适合学习、原型和数据模型较简单的应用。
sqliteorz 基于 SQLiteOpenHelper 和反射提供建表、对象映射、CRUD、事务批量写入、
多数据库和版本迁移能力。
sqliteorz 的目标是保持简单。如果项目需要关系映射、复杂查询、响应式数据流或编译期 SQL 校验,建议使用 Room。
- 模型继承
DBBaseModel即可使用,无需注解或代码生成。 - 自动创建数据表,内置
id、createTime和updateTime字段。 - 支持单条及批量写入、条件查询、排序、分页、更新、删除和计数。
- 查询条件通过
whereArgs绑定,更新值通过ContentValues绑定。 - 批量写入自动分批并使用事务。
- 支持多个数据库、非破坏性迁移及显式破坏性重建。
- 最低支持 Android 5.0(API 21),库本身没有第三方运行时依赖。
在项目的 settings.gradle 中加入 JitPack:
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
maven { url "https://jitpack.io" }
}
}在应用模块中添加依赖:
dependencies {
implementation "com.github.lawnvi:sqliteorz:2.0.0"
}模型必须继承 DBBaseModel,并提供可访问的无参构造函数。Kotlin 构造参数都有默认值时,
编译器会生成可用的无参构造函数。
data class User(
var name: String = "",
var age: Int = 0,
var enabled: Boolean = true,
) : DBBaseModel() {
override fun getTableName() = "users"
}建议显式覆写 getTableName(),避免包名或类名变化影响已有表名。
支持以下字段类型及对应的可空类型:
| Kotlin 类型 | SQLite 类型 |
|---|---|
Int、Short、Long、Boolean |
INTEGER |
Float、Double |
REAL |
Char、String |
TEXT |
ByteArray |
BLOB |
建议在 Application.onCreate() 中注册模型并初始化:
val driver = DBDriver(
name = "app.db",
version = 1,
).apply {
registerModel(User::class.java)
}
OrzHelper.initialize(
applicationContext,
drivers = arrayOf(driver),
)数据库默认保存在应用内部数据库目录,不需要存储权限。
val user = User(name = "张三", age = 20)
check(user.save())
val adults = DBOrz.findModels<User>(
where = "age >= ? AND enabled = ?",
whereArgs = arrayOf("18", "1"),
orderMap = linkedMapOf("age" to -1),
)
val userById = DBOrz.findOne<User>(id = user.id)
val count = DBOrz.count<User>(
where = "age >= ?",
whereArgs = arrayOf("18"),
)orderMap 的值大于 0 表示升序,其他值表示降序。查询全部数据时显式使用
where = "1=1"。
分页查询:
val page = DBOrz.findModels<User>(
where = "1=1",
orderMap = linkedMapOf("id" to -1),
limit = 20,
offset = 40,
)所有外部输入都应通过 ? 和 whereArgs 绑定,不要直接拼接到 SQL 中。
已保存的模型可以直接操作当前记录:
user.update(mapOf("name" to "李四", "enabled" to false))
user.delete()也可以按条件批量操作:
DBOrz.update<User>(
setMaps = mapOf("enabled" to false),
where = "age < ?",
whereArgs = arrayOf("18"),
)
DBOrz.delete<User>(
where = "enabled = ?",
whereArgs = arrayOf("0"),
)为避免误操作,更新和删除全部数据时必须显式传入 where = "1=1"。
val users = List(1_000) { index ->
User(name = "user-$index", age = 18 + index % 50)
}
DBOrz.saveModels(users)批量数据会按每 500 条一组执行事务。同一批模型必须属于同一张表。
每个模型只能注册到一个数据库。配置多个数据库时,需要显式指定默认数据库:
val mainDriver = DBDriver("main.db").apply {
registerModel(User::class.java)
}
val cacheDriver = DBDriver("cache.db").apply {
registerModel(CacheEntry::class.java)
}
OrzHelper.initialize(
applicationContext,
default = "main.db",
drivers = arrayOf(mainDriver, cacheDriver),
)sqliteorz 会根据模型注册关系自动选择对应数据库。
数据库版本增加时应注册迁移;没有迁移策略会直接抛出异常,避免静默丢失数据:
val driver = DBDriver(name = "app.db", version = 2)
.migrateWith { db, oldVersion, _ ->
if (oldVersion < 2) {
db.execSQL("ALTER TABLE users ADD COLUMN email TEXT")
}
}
driver.registerModel(User::class.java)仅对缓存等允许丢失数据的数据库启用破坏性重建:
driver.fallbackToDestructiveMigration()字段重命名、删除、类型变化及索引变更都需要在迁移中自行处理。
需要加密、压缩等自定义写入逻辑时,可以覆写 toContentValues():
override fun toContentValues() = super.toContentValues().apply {
put("content", encrypt(content))
}如果同时需要自定义读取逻辑,可覆写 cursor2Model(),并确保读写格式一致。
- 原来的
fieldStr()、valueStr()扩展点应迁移到toContentValues()。 - 模型主键
id从Int调整为Long,使用主键变量的业务代码需要同步修改类型。 ByteArray新数据使用原生 SQLiteBLOB,读取时兼容旧版 Base64 文本。- 默认数据库改用应用内部数据库目录;检测到旧的应用专属外部目录数据库时会继续使用旧路径。
- 升级前请备份真实业务数据库,并为每个数据库版本变化提供迁移。
- 主键使用 SQLite
INTEGER PRIMARY KEY,在模型中映射为Long。 - 表结构和对象映射依赖运行时反射,没有编译期字段或 SQL 校验。
- 不提供表关联、对象关系、LiveData、Flow 或跨进程访问能力。
- 查询条件使用 SQLite selection 字符串,复杂查询可直接使用原生 SQLite 或改用 Room。