Room Database

1. 前言

ORM,Object Relational Mapping,对象关系映射,用于实现面向对象编程语言里不同类型系统的数据之间的转换。

目前有很多优秀的第三方框架比如:

上面这些也不是不能用,但是每次要用的时候左看看右看看,选数据库都要选个半天,直接用原生的 Room 比较省事啦。

2. Room 是什么

Room 在 SQLite 上提供了一个抽象层,以便在充分利用 SQLite 的强大功能的同时,能够流畅地访问数据库。

Room 主要包含三个主要的组件:

  1. 数据库:包含数据库持有者,并作为应用已保留的持久关系型数据的底层连接的主要接入点。使用 @Database 注解的类应该满足以下三个条件:
    • 该类是继承 RoomDatabase 的抽象类。
    • 在注解中需要添加与数据库关联的实体列表
    • 需要包含具 0 个参数且返回使用 @Dao 注解的类的抽象方法。

在运行时,可以通过调用 Room.databaseBuilder() 或 Room.inMemoryDatabaseBuilder() 获取 Database 的实例。

  1. Entity:实体,表示数据库中的表。
  2. DAO:包含用于访问数据库的方法。

首先,使用 Room 数据库来获取与该数据库相关联的数据访问对象 (DAO)。然后,使用每个 DAO 从数据库中获取实体,再将对这些实体的所有更改保存回数据库中。 最后,使用实体来获取和设置与数据库中的表列相对应的值。

3. 使用方法

3.1 添加依赖

Java

    dependencies {
      def room_version = "2.2.5"

      implementation "androidx.room:room-runtime:$room_version"
      annotationProcessor "androidx.room:room-compiler:$room_version"

      // optional - RxJava support for Room
      implementation "androidx.room:room-rxjava2:$room_version"

      // optional - Guava support for Room, 
      // including Optional and ListenableFuture
      implementation "androidx.room:room-guava:$room_version"

      // optional - Test helpers
      testImplementation "androidx.room:room-testing:$room_version"
    }

Kotlin

    dependencies {
      def room_version = "2.2.5"

      implementation "androidx.room:room-runtime:$room_version"
      kapt "androidx.room:room-compiler:$room_version"

      // optional - Kotlin Extensions and Coroutines support for Room
      implementation "androidx.room:room-ktx:$room_version"

      // optional - Test helpers
      testImplementation "androidx.room:room-testing:$room_version"
    }

3.2 创建Entity

在 Entity 中,至少需要包含一个主键 @PrimaryKey

Java

    @Entity
    public class User {
        @PrimaryKey
        public int uid;

        @ColumnInfo(name = "first_name")
        public String firstName;

        @ColumnInfo(name = "last_name")
        public String lastName;
    }

Kotlin

    @Entity
    data class User(
        @PrimaryKey val uid: Int,
        @ColumnInfo(name = "first_name") val firstName: String?,
        @ColumnInfo(name = "last_name") val lastName: String?
    )

3.3 创建DAO

DAO 表示数据访问对象,在 DAO 中,需要创建一系列用于访问数据库的方法,典型的包括下面的增删改查操作。

Java

    @Dao
    public interface UserDao {
        @Query("SELECT * FROM user")
        List<User> getAll();

        @Query("SELECT * FROM user WHERE uid IN (:userIds)")
        List<User> loadAllByIds(int[] userIds);

        @Query("SELECT * FROM user WHERE first_name LIKE :first AND " +
               "last_name LIKE :last LIMIT 1")
        User findByName(String first, String last);

        @Insert
        void insertAll(User... users);

        @Delete
        void delete(User user);

        @Update
        void update(User user);
    }

Kotlin

    @Dao
    interface UserDao {
        @Query("SELECT * FROM user")
        fun getAll(): List<User>

        @Query("SELECT * FROM user WHERE uid IN (:userIds)")
        fun loadAllByIds(userIds: IntArray): List<User>

        @Query("SELECT * FROM user WHERE first_name LIKE :first AND " +
               "last_name LIKE :last LIMIT 1")
        fun findByName(first: String, last: String): User

        @Insert
        fun insertAll(vararg users: User)

        @Delete
        fun delete(user: User)

        @Update
        fun update(user: User)
    }
    

3.4 创建数据库

数据库类需要使用 @Database 来注解,且在紧跟着的括号中,要添加与该数据库相关联的实体列表,如代码中的 User.class。注解中的 version 代表版本号。

如果应用在单个进程中运行,在实例化 AppDatabase 对象时应遵循单例设计模式。每个 RoomDatabase 实例的成本相当高,而应用几乎不需要在单个进程中访问多个实例。

Java

    @Database(entities = {User.class}, version = 1)
    public abstract class AppDatabase extends RoomDatabase {
        public abstract UserDao userDao();

        public static synchronized AppDatabase getInstance(Context context) {
          if (instance == null) {
              instance = create(context);
          }
          return instance;
        }

        private static AppDatabase create(Context context) {
          return Room.databaseBuilder(getApplicationContext(),
                    AppDatabase.class, "database-name").build();
        }
    }
    

Kotlin

    @Database(entities = arrayOf(User::class), version = 1)
    abstract class AppDatabase : RoomDatabase() {
        abstract fun userDao(): UserDao
    }

    @Synchronized
    fun getInstance(context: Context): AppDatabase {
        if (instance == null) {
            instance = create(context)
        }
        return instance
    }

    private fun create(context: Context): AppDatabase {
        return Room.databaseBuilder(
            applicationContext,
            AppDatabase::class.java, "database-name"
        ).build()
}
    

3.5 使用数据库

创建数据库实例之后就可以愉快的增删改查啦。

Java

    AppDatabase db;
    db = AppDatabase.getInstance(context);
    // 增
    db.userDao().insertAll(users);
    // 删
    db.userDao().delete(user);
    // 改 
    db.userDao().update(user);
    // 查
    List<User> users = db.userDao().getAll();

Kotlin

    val db: AppDatabase
    db = AppDatabase.getInstance(context)
    // 增
    db.userDao().insertAll(users)
    // 删
    db.userDao().delete(user)
    // 改 
    db.userDao().update(user)
    // 查
    val users = db.userDao().getAll()

4. 注意事项

使用过程中碰到了一些坑,之后补充在这里。#TODO

5. 参考

发表评论

Fill in your details below or click an icon to log in:

WordPress.com 徽标

您正在使用您的 WordPress.com 账号评论。 注销 /  更改 )

Google photo

您正在使用您的 Google 账号评论。 注销 /  更改 )

Twitter picture

您正在使用您的 Twitter 账号评论。 注销 /  更改 )

Facebook photo

您正在使用您的 Facebook 账号评论。 注销 /  更改 )

Connecting to %s