天天看點

Android資料庫元件Room

Room是Android官方提供的sqlite資料庫管理元件。

添加依賴

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'

android {
    ...
    defaultConfig {
        ...
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = ["room.schemaLocation": "$projectDir/build/room/schemas".toString()]
            }
        }
    }
    ...
}

dependencies {
    ...
    def room_version = "1.1.1"
    implementation "android.arch.persistence.room:runtime:$room_version"
    kapt "android.arch.persistence.room:compiler:$room_version" 
    implementation "android.arch.persistence.room:rxjava2:$room_version"
    implementation "android.arch.persistence.room:guava:$room_version"
    testImplementation "android.arch.persistence.room:testing:$room_version"
}
           

建立資料庫

val accountDB: AccountDB = Room.databaseBuilder(context, AccountDB::class.java, "account.db")
            .allowMainThreadQueries()//允許在主線程查詢(如果不允許主線程查詢,可以使用LiveData)
            .fallbackToDestructiveMigration()//資料庫版本更新,清空資料庫
            .addMigrations(migration_1_2)//資料庫版本更新,修改資料庫
            .build()
           
@Database(entities = [User::class, Phone::class], version = 1)
abstract class AccountDB : RoomDatabase() {

    abstract fun userDao(): UserDao

    abstract fun phoneDao(): PhoneDao

}
           

定義實體表

@Entity(tableName = "user")
class User {

    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "id")
    var id: Long = 0

    @ColumnInfo(name = "nickname")
    var nickname: String = ""

    @ColumnInfo(name = "birthday")
    var birthday: Long = 0

    @Ignore
    var picture: Bitmap? = null

}
           
@Entity(tableName = "phone")
class Phone {

    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "id")
    var id: Long = 0

    @ColumnInfo(name = "num")
    var num: String = ""

    @ColumnInfo(name = "userId")
    var userId: Long = 0

}
           

Dao類

@Dao
interface UserDao {

    @Query("SELECT * FROM user")
    fun query(): List<User>

    @Query("SELECT * FROM user")
    fun queryLiveData(): LiveData<List<User>>

    @Query("SELECT * FROM user WHERE id IN (:userIds)")
    fun queryByIds(vararg userIds: Int): List<User>

    @Query("SELECT * FROM user WHERE nickname LIKE :nickname")
    fun queryByNickname(nickname: String): List<User>

    @Insert
    fun insert(user: User):Long

    @Update
    fun update(user: User):Int

    @Delete
    fun delete(user: User):Int

    @Transaction
    @Query("SELECT * FROM user")
    fun queryUserAndPhone(): List<UserAndPhone>

}
           
@Dao
interface PhoneDao {

    @Insert
    fun insert(phone: Phone):Long

}
           

資料庫查詢

val accountDB = Room.databaseBuilder(App.context, AccountDB::class.java, "account.db")
    .allowMainThreadQueries()
    .build()
val user = User()
accountDB.userDao().insert(user)//新增
accountDB.userDao().query()//查詢
accountDB.userDao().update(user)//修改
accountDB.userDao().delete(user)//删除
           

事務處理

val accountDB = Room.databaseBuilder(App.context, AccountDB::class.java, "account.db")
    .allowMainThreadQueries()
    .build()
try {
    //執行事務
    accountDB.runInTransaction {
        val user = User()

        //插入資料
        DBUtil.accountDB.userDao().insert(user)

        "a".toInt()//異常
    }
} catch (e: Exception) {
    e.printStackTrace()
    Toast.makeText(this, "異常,資料復原", Toast.LENGTH_SHORT).show()
}
           

LiveData查詢

val accountDB = Room.databaseBuilder(App.context, AccountDB::class.java, "account.db")
    .allowMainThreadQueries()
    .build()
accountDB.userDao().queryLiveData().observe(this, Observer {list->
    log(list.toString())
})
           

關聯查詢

class UserAndPhone {

    @Embedded
    var user: User = User()

    @Relation(parentColumn = "id", entityColumn = "userId")
    var phoneList: List<Phone> = ArrayList()

    override fun toString(): String {
        return "UserAndPhone(user=$user, phoneList=$phoneList)"
    }

}
           
@Dao
interface UserDao {

    @Transaction
    @Query("SELECT * FROM user")
    fun queryUserAndPhone(): List<UserAndPhone>

}
           

資料庫版本更新

val migration_1_2: Migration = object : Migration(1, 2) {
    override fun migrate(database: SupportSQLiteDatabase) {
        database.execSQL("ALTER TABLE user ADD birthday INTEGER NOT NULL DEFAULT 0")
    }
}

val accountDB = Room.databaseBuilder(App.context, AccountDB::class.java, "account.db")
    .allowMainThreadQueries()
    .addMigrations(migration_1_2)
    .build()
           

RoomDemo:https://github.com/dingjianlun/RoomDemo