[关闭]
@cxm-2016 2017-02-04T23:49:21.000000Z 字数 4034 阅读 3701

Anko:操作数据库

Kotlin

版本:1
作者:陈小默
声明:禁止转载

原文地址:Anko-SQLite


使用Gradle配置

我们需要在你的 build.gradle 文件添加下面的内容:

  1. compile 'org.jetbrains.anko:anko-sqlite:0.9'

引入db包

  1. import org.jetbrains.anko.db.*

访问数据库

传统的数据库访问方式,我们需要创建一个DatabaseOpenHelper类,然后重写其中包含的方法。就像下面这个样子:

  1. class MyDatabaseOpenHelper(ctx: Context) : ManagedSQLiteOpenHelper(ctx, "MyDatabase", null, 1) {
  2. companion object {
  3. private var instance: MyDatabaseOpenHelper? = null
  4. @Synchronized
  5. fun getInstance(ctx: Context): MyDatabaseOpenHelper {
  6. if (instance == null) {
  7. instance = MyDatabaseOpenHelper(ctx.getApplicationContext())
  8. }
  9. return instance!!
  10. }
  11. }
  12. override fun onCreate(db: SQLiteDatabase) {
  13. // 创建数据库
  14. db?.createTable("Customer", ifNotExists = true,
  15. "_id" to INTEGER + PRIMARY_KEY + UNIQUE,
  16. "name" to TEXT,
  17. "photo" to BLOB)
  18. }
  19. override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
  20. // 如果需要的话,在这里升级数据库
  21. db?.dropTable("User", true)
  22. }
  23. }
  24. // 扩展Context的访问方式
  25. val Context.database: MyDatabaseOpenHelper
  26. get() = MyDatabaseOpenHelper.getInstance(getApplicationContext())

对于Anko,我们只需要通过下面这段简单的代码就能够创建一个数据库:

  1. database.use {
  2. // 现在`this`就是一个SQLiteDatabase实例
  3. }

接下来写一段异步加载数据库并回调的示例:

  1. class SomeActivity : Activity() {
  2. private fun loadAsync() {
  3. doAsync {
  4. val result = database.use {
  5. // TODO
  6. }
  7. uiThread { loadComplete(result) }
  8. }
  9. }
  10. }

创建或者销毁数据表

使用Anko能够方便的创建和销毁一张数据表,它的语法像这样:

  1. database.use {
  2. createTable("Customer", true,
  3. "_id" to INTEGER + PRIMARY_KEY + UNIQUE,
  4. "name" to TEXT,
  5. "photo" to BLOB)
  6. }

目前支持五种类型: NULL, INTEGER, REAL, TEXTBLOB. 对于PRIMARY KEY 或者 UNIQUE 的设定,可以在类型之后使用+设置.

使用dropTable方法可以销毁数据表:

  1. dropTable("User", true)

向表中插入数据

通常情况下,我们需要使用ContentValues对象来向表中插入一行数据,就像下面这样:

  1. val values = ContentValues()
  2. values.put("_id", 5)
  3. values.put("name", "John Smith")
  4. values.put("email", "user@domain.org")
  5. db.insert("User", null, values)

Anko 使用更简洁的方式来实现插入操作:

  1. db.insert("User",
  2. "_id" to 42,
  3. "name" to "John",
  4. "email" to "user@domain.org"
  5. )

也可以在数据库初始化的时候调用:

  1. database.use {
  2. insert("User",
  3. "_id" to 42,
  4. "name" to "John",
  5. "email" to "user@domain.org"
  6. }

insertOrThrow(), replace(), replaceOrThrow() 都是可用的方法。

查询数据

在查询过程中,Anko提供了如下约束方法:

Method Description
column(String) Add a column to select query
distinct(Boolean) Distinct query
where(String) Specify raw String where query
where(String, args) :star: Specify a where query with arguments
where?(String, args) Specify a where query with ? mark arguments
orderBy(String, [ASC/DESC]) Order by this column
groupBy(String) Group by this column
limit(count: Int) Limit query result row count
limit(offset: Int, count: Int) Limit query result row count with an offset
having(String) Specify raw having expression
having(String, args) :star: Specify a having expression with arguments

查询过程支持参数解析,于是我们可以将一次查询写成下面的样子:

  1. db.select("User", "name")
  2. .where("(_id > {userId}) and (name = {userName})",
  3. "userName" to "John",
  4. "userId" to 42)

在这里{userId}部分会被替换为42 并且 {userName}被替换为'John'`。

where?方法仅支持 String 类型.

通过 exec() 方法我们可以执行此次插叙.它通过扩展接受一个Lambda表达式 Cursor.() -> T.

  1. db.select("User", "email").exec {
  2. // Doing some stuff with emails
  3. }

解析查询结果

当我们或得到 Cursor 对象之后, Anko提供了如下方法解析对象。

Method Description
parseSingle(rowParser): T 严格的解析一行,或得到一个对象。
parseOpt(rowParser): T? 解析一行得到对象,或没有数据返回null。
parseList(rowParser): List<T> 解析任意多行数据。

目前支持两种类型的解析器:

  1. interface RowParser<T> {
  2. fun parseRow(columns: Array<Any>): T
  3. }
  4. interface MapRowParser<T> {
  5. fun parseRow(columns: Map<String, Any>): T
  6. }

Anko还提供了解析单行单列数据的解析器:

另外你也可以自己创建一个Bean类用于解析,必须将属性声明到主构造器当中:

  1. class Person(val firstName: String, val lastName: String, val age: Int)

通过上面的类创建解析器:

  1. val rowParser = classParser<Person>()

目前Anko不支持通过主构造器中的可选参数创建解析器。目前使用的是通过Java反射构造方法传入传入生成解析器。

自定义行解析器

让我们自定义个行解析器 (Int, String, String).最简单的方式如下:

  1. class MyRowParser : RowParser<Triple<Int, String, String>> {
  2. override fun parseRow(columns: Array<Any>): Triple<Int, String, String> {
  3. return Triple(columns[0] as Int, columns[1] as String, columns[2] as String)
  4. }
  5. }

我们可以通过Lambda表达式简化上述过程:

  1. val parser = rowParser { id: Int, name: String, email: String ->
  2. Triple(id, name, email)
  3. }

Cursor

不要忘记关闭Cursor对象

更新数据

将User表中符合条件的name属性设置为Alice

  1. update("User", "name" to "Alice")
  2. .where("_id = {userId}", "userId" to 42)
  3. .exec()

我们也可以通过 where?() 函数来使用传统的占位方式:

  1. update("User", "name" to "Alice")
  2. .`where?`("_id = ?", 42)
  3. .exec()

开启事务

以下方法与允许你在其中使用事务操作一个数据库。

  1. transaction {
  2. // Your transaction code
  3. }

Transaction will be marked marked as successful if no exception was thrown inside the {} block.

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注