@cxm-2016
2017-02-04T23:49:21.000000Z
字数 4034
阅读 3681
Kotlin
版本:1
作者:陈小默
声明:禁止转载
原文地址:Anko-SQLite
我们需要在你的 build.gradle
文件添加下面的内容:
compile 'org.jetbrains.anko:anko-sqlite:0.9'
import org.jetbrains.anko.db.*
传统的数据库访问方式,我们需要创建一个DatabaseOpenHelper
类,然后重写其中包含的方法。就像下面这个样子:
class MyDatabaseOpenHelper(ctx: Context) : ManagedSQLiteOpenHelper(ctx, "MyDatabase", null, 1) {
companion object {
private var instance: MyDatabaseOpenHelper? = null
@Synchronized
fun getInstance(ctx: Context): MyDatabaseOpenHelper {
if (instance == null) {
instance = MyDatabaseOpenHelper(ctx.getApplicationContext())
}
return instance!!
}
}
override fun onCreate(db: SQLiteDatabase) {
// 创建数据库
db?.createTable("Customer", ifNotExists = true,
"_id" to INTEGER + PRIMARY_KEY + UNIQUE,
"name" to TEXT,
"photo" to BLOB)
}
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
// 如果需要的话,在这里升级数据库
db?.dropTable("User", true)
}
}
// 扩展Context的访问方式
val Context.database: MyDatabaseOpenHelper
get() = MyDatabaseOpenHelper.getInstance(getApplicationContext())
对于Anko,我们只需要通过下面这段简单的代码就能够创建一个数据库:
database.use {
// 现在`this`就是一个SQLiteDatabase实例
}
接下来写一段异步加载数据库并回调的示例:
class SomeActivity : Activity() {
private fun loadAsync() {
doAsync {
val result = database.use {
// TODO
}
uiThread { loadComplete(result) }
}
}
}
使用Anko能够方便的创建和销毁一张数据表,它的语法像这样:
database.use {
createTable("Customer", true,
"_id" to INTEGER + PRIMARY_KEY + UNIQUE,
"name" to TEXT,
"photo" to BLOB)
}
目前支持五种类型: NULL
, INTEGER
, REAL
, TEXT
和BLOB
. 对于PRIMARY KEY
或者 UNIQUE
的设定,可以在类型之后使用+
设置.
使用dropTable
方法可以销毁数据表:
dropTable("User", true)
通常情况下,我们需要使用ContentValues
对象来向表中插入一行数据,就像下面这样:
val values = ContentValues()
values.put("_id", 5)
values.put("name", "John Smith")
values.put("email", "user@domain.org")
db.insert("User", null, values)
Anko 使用更简洁的方式来实现插入操作:
db.insert("User",
"_id" to 42,
"name" to "John",
"email" to "user@domain.org"
)
也可以在数据库初始化的时候调用:
database.use {
insert("User",
"_id" to 42,
"name" to "John",
"email" to "user@domain.org"
}
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 |
查询过程支持参数解析,于是我们可以将一次查询写成下面的样子:
db.select("User", "name")
.where("(_id > {userId}) and (name = {userName})",
"userName" to "John",
"userId" to 42)
在这里{userId}
部分会被替换为42
并且 {userName}
被替换为'John'`。
where?
方法仅支持 String
类型.
通过 exec()
方法我们可以执行此次插叙.它通过扩展接受一个Lambda表达式 Cursor.() -> T
.
db.select("User", "email").exec {
// Doing some stuff with emails
}
当我们或得到 Cursor
对象之后, Anko提供了如下方法解析对象。
Method | Description |
---|---|
parseSingle(rowParser): T |
严格的解析一行,或得到一个对象。 |
parseOpt(rowParser): T? |
解析一行得到对象,或没有数据返回null。 |
parseList(rowParser): List<T> |
解析任意多行数据。 |
目前支持两种类型的解析器:
interface RowParser<T> {
fun parseRow(columns: Array<Any>): T
}
interface MapRowParser<T> {
fun parseRow(columns: Map<String, Any>): T
}
Anko还提供了解析单行单列数据的解析器:
ShortParser
IntParser
LongParser
FloatParser
DoubleParser
StringParser
BlobParser
另外你也可以自己创建一个Bean类用于解析,必须将属性声明到主构造器当中:
class Person(val firstName: String, val lastName: String, val age: Int)
通过上面的类创建解析器:
val rowParser = classParser<Person>()
目前Anko不支持通过主构造器中的可选参数创建解析器。目前使用的是通过Java反射构造方法传入传入生成解析器。
让我们自定义个行解析器 (Int, String, String)
.最简单的方式如下:
class MyRowParser : RowParser<Triple<Int, String, String>> {
override fun parseRow(columns: Array<Any>): Triple<Int, String, String> {
return Triple(columns[0] as Int, columns[1] as String, columns[2] as String)
}
}
我们可以通过Lambda表达式简化上述过程:
val parser = rowParser { id: Int, name: String, email: String ->
Triple(id, name, email)
}
不要忘记关闭Cursor对象
将User表中符合条件的name属性设置为Alice
update("User", "name" to "Alice")
.where("_id = {userId}", "userId" to 42)
.exec()
我们也可以通过 where?()
函数来使用传统的占位方式:
update("User", "name" to "Alice")
.`where?`("_id = ?", 42)
.exec()
以下方法与允许你在其中使用事务操作一个数据库。
transaction {
// Your transaction code
}
Transaction will be marked marked as successful if no exception was thrown inside the {}
block.