Android架构组件Room的使用详解

作者:simplepeng 时间:2022-04-30 14:59:24 

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的使用详解网站的支持!

来源:https://juejin.im/post/5a4228036fb9a044ff31b8ca?utm_source=tuicool&utm_medium=referral

标签:android,架构组件,room
0
投稿

猜你喜欢

  • rocketmq client 日志的问题处理方式

    2023-07-15 08:10:32
  • springBoot Junit测试用例出现@Autowired不生效的解决

    2023-01-24 12:57:59
  • Android自定义View用切图显示字符串

    2023-03-13 07:14:58
  • java使用spring实现读写分离的示例代码

    2023-03-03 06:44:34
  • java synchronized关键字的用法

    2022-11-19 13:45:25
  • Linux命令行下编译Android NDK的示例代码

    2023-02-13 17:19:54
  • Android编程简单实现九宫格示例

    2021-12-06 21:43:57
  • Android仿天猫横向滑动指示器功能的实现

    2022-10-09 16:53:58
  • springBoot集成Elasticsearch 报错 Health check failed的解决

    2022-12-07 05:18:16
  • 深入解析java中的静态代理与动态代理

    2023-08-23 13:10:56
  • SpringBoot整合MongoDB完整实例代码

    2023-10-22 03:42:48
  • java8学习教程之函数引用的使用方法

    2023-08-28 12:03:19
  • Go Java算法之累加数示例详解

    2023-03-16 00:43:31
  • 解析SpringSecurity自定义登录验证成功与失败的结果处理问题

    2021-09-01 16:42:59
  • java过滤器中Filter的ChainFilter过滤链

    2021-09-29 00:03:42
  • Android开发实现简单计算器功能

    2022-10-17 09:18:16
  • 教你如何使用Java实现WebSocket

    2021-08-22 20:39:02
  • 三种Android单击事件onclick的实现方法

    2022-05-21 16:54:03
  • Android CardView详解及使用方法和实例

    2023-01-11 01:04:30
  • springboot2.x 接入阿里云市场短信发送的实现

    2023-09-20 23:03:57
  • asp之家 软件编程 m.aspxhome.com