Android架构组件Room的使用详解

 更新时间:2017年12月27日 10:20:06   作者:simplepeng  
Room其实就是一个orm,抽象了SQLite的使用。这篇文章给大家介绍了Android架构组件Room的使用详解,需要的朋友参考下吧

Room其实就是一个orm,抽象了SQLite的使用,但是它作为Android的亲儿子orm,并且原生支持LiveData和Rxjava嵌套使用,学习一下还是不错的。

Room有3个主要组件

  • Database :数据库
  • Entity : 代表数据库一个表结构
  • Dao : 包含访问数据库的方法

简单使用

添加Google Maven仓库

allprojects {
  repositories {
    jcenter()
    google()
  }
}

添加依赖

dependencies {
  // Room
  implementation "android.arch.persistence.room:runtime:1.0.0"
  annotationProcessor "android.arch.persistence.room:compiler:1.0.0"
}

定义数据表实体类

班级表

@Entity(tableName = "tb_class")
public class ClassEntity {
  @PrimaryKey
  private long id;
}

学生表

//指示数据表实体类
@Entity(tableName = "tb_student",//定义表名
    indices = @Index(value = {"name", "sex"}, unique = true),//定义索引
    foreignKeys = {@ForeignKey(entity = ClassEntity.class,
        parentColumns = "id",
        childColumns = "class_id")})//定义外键
public class StudentEntity {
  @PrimaryKey //定义主键
  private long id;
  @ColumnInfo(name = "name")//定义数据表中的字段名
  private String name;
  @ColumnInfo(name = "sex")
  private int sex;
  @Ignore//指示Room需要忽略的字段或方法
  private String ignoreText;
  @ColumnInfo(name = "class_id")
  private String class_id;
  //setter and getter
}

Entity注解可选参数

public @interface Entity {
 //定义表名
  String tableName() default "";
 //定义索引
  Index[] indices() default {};
 //设为true则父类的索引会自动被当前类继承
  boolean inheritSuperIndices() default false;
 //定义主键
  String[] primaryKeys() default {};
 //定义外键
  ForeignKey[] foreignKeys() default {};
}

Index索引注解可选参数

public @interface Index {
 //定义需要添加索引的字段
 String[] value();
 //定义索引的名称
 String name() default "";
 //true-设置唯一键,标识value数组中的索引字段必须是唯一的,不可重复
 boolean unique() default false;
}

ForeignKey外键注解可选参数

public @interface ForeignKey {
 //引用外键的表的实体
 Class entity();
 //要引用的外键列
 String[] parentColumns();
 //要关联的列
 String[] childColumns();
 //当父类实体(关联的外键表)从数据库中删除时执行的操作
 @Action int onDelete() default NO_ACTION;
 //当父类实体(关联的外键表)更新时执行的操作
 @Action int onUpdate() default NO_ACTION;
 //在事务完成之前,是否应该推迟外键约束
 boolean deferred() default false;
 //给onDelete,onUpdate定义的操作
 int NO_ACTION = 1;
 int RESTRICT = 2;
 int SET_NULL = 3;
 int SET_DEFAULT = 4;
 int CASCADE = 5;
 @IntDef({NO_ACTION, RESTRICT, SET_NULL, SET_DEFAULT, CASCADE})
 @interface Action {
  }
}

定义Dao类

@Dao
public interface StudentDao {
  @Query("SELECT * FROM StudentEntity")
  List<StudentEntity> getAll();
  @Query("SELECT * FROM StudentEntity WHERE id IN (:ids)")
  List<StudentEntity> getAllByIds(long[] ids);
  @Insert
  void insert(StudentEntity... entities);
  @Delete
  void delete(StudentEntity entity);
  @Update
  void update(StudentEntity entity);
}

@insert, @Update都可以执行事务操作,定义在OnConflictStrategy注解类中

public @interface Insert {
  //定义处理冲突的操作
  @OnConflictStrategy 
  int onConflict() default OnConflictStrategy.ABORT;
}
public @interface OnConflictStrategy {
  //策略冲突就替换旧数据
  int REPLACE = 1;
  //策略冲突就回滚事务
  int ROLLBACK = 2;
  //策略冲突就退出事务
  int ABORT = 3;
  //策略冲突就使事务失败 
  int FAIL = 4;
  //忽略冲突
  int IGNORE = 5;
}

定义数据库

@Database(entities = {StudentEntity.class}, version = 1)
public abstract class RoomDemoDatabase extends RoomDatabase {
  public abstract StudentDao studentDao();
}

生成数据库实例

RoomDemoDatabase database = Room.databaseBuilder(getApplicationContext(),       RoomDemoDatabase.class, "database_name")
        .build();

生成数据库实例的其他操作

Room.databaseBuilder(getApplicationContext(),
            RoomDemoDatabase.class, "database_name")
            .addCallback(new RoomDatabase.Callback() {
              //第一次创建数据库时调用,但是在创建所有表之后调用的
              @Override
              public void onCreate(@NonNull SupportSQLiteDatabase db) {
                super.onCreate(db);
              }

              //当数据库被打开时调用
              @Override
              public void onOpen(@NonNull SupportSQLiteDatabase db) {
                super.onOpen(db);
              }
            })
            .allowMainThreadQueries()//允许在主线程查询数据
            .addMigrations()//迁移数据库使用,下面会单独拿出来讲
            .fallbackToDestructiveMigration()//迁移数据库如果发生错误,将会重新创建数据库,而不是发生崩溃
            .build();

数据库迁移(升级)

Room.databaseBuilder(getApplicationContext(), MyDb.class, "database-name")
    .addMigrations(MIGRATION_1_2, MIGRATION_2_3).build();

static final Migration MIGRATION_1_2 = new Migration(1, 2) {
  @Override
  public void migrate(SupportSQLiteDatabase database) {
    database.execSQL("CREATE TABLE `Fruit` (`id` INTEGER, "
        + "`name` TEXT, PRIMARY KEY(`id`))");
  }
};
static final Migration MIGRATION_2_3 = new Migration(2, 3) {
  @Override
  public void migrate(SupportSQLiteDatabase database) {
    database.execSQL("ALTER TABLE Book "
        + " ADD COLUMN pub_year INTEGER");
  }
};

创建嵌套对象

有时,您希望将一个实体或普通的以前的Java对象(POJO)作为数据库逻辑中的一个完整的整体来表示,即使该对象包含几个字段。在这些情况下,您可以使用@Embedded来表示一个对象,您希望将其分解为表中的子字段。然后可以像对其他单个列一样查询嵌入式字段

class Address {
  public String street;
  public String state;
  public String city;
  @ColumnInfo(name = "post_code")
  public int postCode;
}
@Entity
class User {
  @PrimaryKey
  public int id;
  public String firstName;
  @Embedded
  public Address address;
}

这样user表中的字段就包含了 id , firstName , street , state , city , 和 post_code

注意 :嵌入式字段还可以包含其他嵌入式字段

如果一个实体具有相同类型的多个内嵌字段,则可以通过设置前缀属性(prefix)使每个列保持惟一。然后将所提供的值添加到嵌入对象中每个列名的开头

 @Embedded(prefix = "foo_")
 Coordinates coordinates;

和 LiveData 一起使用

添加依赖

// ReactiveStreams support for LiveData
implementation "android.arch.lifecycle:reactivestreams:1.0.0"

修改返回类型

@Dao
public interface MyDao {
  @Query("SELECT first_name, last_name FROM user WHERE region IN (:regions)")
  public LiveData<List<User>> loadUsersFromRegionsSync(List<String> regions);
}

和RxJava一起使用

添加依赖

// RxJava support for Room
implementation "android.arch.persistence.room:rxjava2:1.0.0"

修改返回类型

@Dao
public interface MyDao {
  @Query("SELECT * from user where id = :id LIMIT 1")
  public Flowable<User> loadUserById(int id);
}

直接游标访问

@Dao
public interface MyDao {
  @Query("SELECT * FROM user WHERE age > :minAge LIMIT 5")
  public Cursor loadRawUsersOlderThan(int minAge);
}

类型转换

定义转换类,@TypeConverter注解定义转换的方法

public class Converters {
  @TypeConverter
  public static Date fromTimestamp(Long value) {
    return value == null ? null : new Date(value);
  }
  @TypeConverter
  public static Long dateToTimestamp(Date date) {
    return date == null ? null : date.getTime();
  }
}

@TypeConverters注解,告知数据库要依赖哪些转换类

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

使用这些转换器,您可以在其他查询中使用您的自定义类型,正如您将使用基本类型一样,如下代码所示

@Entity
public class User {
  ...
  private Date birthday;
}
@Dao
public interface UserDao {
  ...
  @Query("SELECT * FROM user WHERE birthday BETWEEN :from AND :to")
  List<User> findUsersBornBetweenDates(Date from, Date to);
}

输出模式

在编译时,将数据库的模式信息导出到JSON文件中,这样可有利于我们更好的调试和排错

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

您应该将导出的JSON文件(表示数据库的模式历史记录)存储在您的版本控制系统中,因为它允许为测试目的创建您的数据库的旧版本

总结

以上所述是小编给大家介绍的Android架构组件Room的使用详解,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

相关文章

  • Android开发手册shape属性和子属性使用说明

    Android开发手册shape属性和子属性使用说明

    这篇文章主要为大家介绍了Android开发手册shape属性和子属性使用说明,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-06-06
  • 深入理解TextView实现Rich Text--在同一个TextView设置不同字体风格

    深入理解TextView实现Rich Text--在同一个TextView设置不同字体风格

    本篇文章是对Android中在同一个TextView中设置不同的字体风格进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • Android 中按home键和跳转到主界面的实例代码

    Android 中按home键和跳转到主界面的实例代码

    本文通过实例代码给大家分享Android 中按home键和跳转到主界面的方法,非常不错,具有参考借鉴价值,需要的朋友参考下吧
    2017-04-04
  • Android Glide常见使用方式讲解

    Android Glide常见使用方式讲解

    对于Glide这个加载图片的框架,很多人都在用,我之前使用的是ImageLoader,最近查资料时,发现Glide才是Google推荐的加载图片框架,功能非常强大,而且还有Google专人维护,要知道,ImageLoader已经没人维护了,除了问题可没人解答。所以有必要整理一下Glide的使用
    2023-01-01
  • android @override 报错解决方案

    android @override 报错解决方案

    android @override 报错:就是说Java 1.5的编译器默认对父类的方法进行覆盖,采用@Override进行说明;但1.6已经扩展到对接口的方法;所以如果还是以Java 1.5的编译器来编译的话,会出现错误
    2012-12-12
  • Android自定义view实现日历打卡签到

    Android自定义view实现日历打卡签到

    这篇文章主要为大家详细介绍了Android自定义view实现日历打卡签到,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-05-05
  • Android实现关机与重启的几种方式(推荐)

    Android实现关机与重启的几种方式(推荐)

    这篇文章主要介绍了Android实现关机与重启的几种方式(推荐)的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2016-07-07
  • Android快速实现发送邮件实例

    Android快速实现发送邮件实例

    本篇文章主要介绍了Android快速实现发送邮件实例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-04-04
  • Android中EditText的drawableRight属性设置点击事件

    Android中EditText的drawableRight属性设置点击事件

    这篇文章主要介绍了Android中EditText的drawableRight属性的图片设置点击事件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-10-10
  • Android 补间动画及组合AnimationSet常用方法详解

    Android 补间动画及组合AnimationSet常用方法详解

    这篇文章主要为大家介绍了Android 补间动画及组合AnimationSet常用方法详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-11-11

最新评论