Room数据库框架使用介绍

Google最近出了个数据库框架名字叫Room Persistence Library,基于SQLite的封装。
它是一个数据库对象映射库,它提供了方便的API在Android应用程序上来操作数据库。
相关官方说明,链接:android.arch.persistence.room
以下是关于Room 简单集成使用,非常推荐,简直就是数据库中Retrofit。


引入room

  • 项目根build.gradle中添加
    1
    2
    3
    4
    5
    6
    allprojects {
    repositories {
    jcenter()
    google() // 添加google 的maven库
    }
    }
  • modules的build.gradle中添加
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    //room
    implementation "android.arch.persistence.room:runtime:1.0.0"

    //如果是 kotlin 环境,使用 kapt 来操作注解
    annotationProcessor "android.arch.persistence.room:compiler:1.0.0"

    // 以下为可选
    //room 支持RxJava2 库
    implementation "android.arch.persistence.room:rxjava2:1.0.0"

    implementation "android.arch.lifecycle:extensions:1.0.0"
    implementation "android.arch.persistence.room:runtime:1.0.0"
    annotationProcessor "android.arch.lifecycle:compiler:1.0.0"

@Entity 注解创建对应数据库表

相关注解解释:

  • @Entity 指明表,将类标记为实体类名。
    • 实现时,注意实现其构造函数,否则报错
    • 默认表名为实体类名,也可通过 tableName 指定表名
    • 可使用 indices 创建索引
    • foreignKeys 方式可以指定表的外键
      1
      2
      3
      4
      5
      6
      7
      8
      @Entity(foreignKeys = {
      @ForeignKey(entity = Book.class,
      parentColumns = "id",
      childColumns = "book_id"),

      @ForeignKey(entity = User.class,
      parentColumns = "id",
      childColumns = "user_id")})
      以下是User实体类示例
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      @Entity(tableName = "users", primaryKeys = "name",indices={@Index("name")})
      @TypeConverters(DateConverter.class)
      public class User {
      //...
      @PrimaryKey
      @NonNull
      public int id;
      public String name;
      public String lastName;
      public int age;
      @Ignore
      public String nick;
      public Date startTime;
      }
  • @PrimaryKey 主键,自增的话指明 autoGenerate 为 true
  • @ColumnInfo 指定列,默认列表为属性名,也可通过name 指定列名
  • 有些字段的数据类型不支持,通过 @TypeConverters 处理
    DateConverter 的实现代码如下
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public class DateConverter {
    @TypeConverter
    public static Date toDate(Long timestamp) {
    return timestamp != null ? new Date(timestamp):null;
    }

    @TypeConverter
    public static Long toTimestamp(Date date) {
    return date != null ? date.getTime():null;
    }
    }

@Dao 创建相关sql方法

  • @Dao 指明为 Dao 类
  • @Insert 插入操作 onConflict 相关属性,处理不同情况
    • REPLACE
    • ROLLBACK
    • ABORT
    • FAIL
    • IGNORE
  • @Update 更新操作
  • @Delete 删除操作
  • @Query 查询操作 ,需要指定 Sql 语句
    示例代码:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    @Dao
    public interface UserDao {

    @Insert(onConflict = IGNORE)
    void insertUser(User user);

    @Insert(onConflict = REPLACE)
    void insertOrReplaceUsers(User... users);

    @Delete
    void deleteUser(User user);

    @Delete
    void deleteUsers(User user1, User user2);

    @Query("DELETE FROM User")
    void deleteAll();

    @Query("select * from user")
    List<User> loadAllUsers();

    @Query("select * from user where name = :firstName and lastName = :lastName")
    List<User> findUserByNameAndLastName(String firstName, String lastName);

    @Query("SELECT * FROM User WHERE age < :age")
    List<User> findUsersYoungerThanSolution(int age);
    }

@Database 实现RoomDatabase

  • @Database 指定操作,将 Dao 层全部集中在一起,可以指定 version 使用 entities 指定所用的 entity(table)
    • entities 制定该数据存在的表
    • version 指定版本号
  • @TypeConverters 指定转换器
    示例代码如下:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    @Database(entities = {User.class, Book.class}, version = 1)
    public abstract class AppDatabase extends RoomDatabase {

    private static AppDatabase INSTANCE;

    public abstract UserDao userModel();

    public abstract BookDao bookModel();

    public static AppDatabase getInMemoryDatabase(Context context) {
    if (INSTANCE == null) {
    INSTANCE =
    //Room.inMemoryDatabaseBuilder(context.getApplicationContext(), AppDatabase.class)//不指定数据库名,用默认
    Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class,"db_name")//指定数据库名
    // To simplify the codelab, allow queries on the main thread.
    // Don't do this on a real app! See PersistenceBasicSample for an example.
    .allowMainThreadQueries()//运行在主线程查询
    .addCallback(new Callback() {
    @Override public void onCreate(@NonNull SupportSQLiteDatabase db) {
    super.onCreate(db);
    }

    @Override public void onOpen(@NonNull SupportSQLiteDatabase db) {
    super.onOpen(db);
    }
    })
    .addMigrations(new Migration(1, 2) {//数据库升级可用
    @Override public void migrate(@NonNull SupportSQLiteDatabase database) {
    //从1版本升级到2版本
    }
    }, new Migration(2,3) {
    @Override public void migrate(@NonNull SupportSQLiteDatabase database) {
    //从2版本升级到3版本
    }
    })
    .build();
    }
    return INSTANCE;
    }

    public static void destroyInstance() {
    INSTANCE = null;
    }
    }

相关实际运用

  • 简单查询操作
    1
    2
    AppDatabase db = AppDatabase.getInMemoryDatabase(context);
    db.userModel().insertUser(user);
  • 简单删除操作
    1
    2
    AppDatabase db = AppDatabase.getInMemoryDatabase(context);
    db.userModel().deleteUser(user);

相关问题

  • Error:Entities and Pojos must have a usable public constructor.
    解决方案:需要实体类实现构造函数
  • Error:Cannot figure out how to save this field into database. You can consider adding a type converter for it.
    Error:Cannot figure out how to read this field from a cursor.
    解决方案:有些字段或类型不认识,需要在 converter 进行转换
  • Cannot access database on the main thread since it may potentially lock the UI for a long period of time
    解决方案:据库操作放在 io 线程,不要在 ui 线程做。
  • Room cannot verify the data integrity. Looks like you’ve changed schema but forgot to update the version number. You can simply fix this by increasing the version number
    解决方案:数据库改变,需要使用版本更新操作。

相关参考