Android架构组件Room指南


本文整理自网络,侵删。

一、简介

Room是Google推出的Android架构组件库中的数据持久化组件库, 也可以说是在SQLite上实现的一套ORM解决方案。

Room主要包含三个部分:

  • Database : 持有DB和DAO
  • Entity : 定义POJO类,即数据表结构
  • DAO(Data Access Objects) : 定义访问数据(增删改查)的接口

其关系如下图所示:

Room Architecture Diagram

二、基本使用

1. 创建Entity

1.1 一个简单的Entitiy

一个简单Entity定义如下:

@Entity(tableName = "user" 
  indices = {@Index(value = {"first_name", "last_name"})})
public class User {
 @PrimaryKey
 private int uid;
 @ColumnInfo(name = "first_name")
 private String firstName;
 @ColumnInfo(name = "last_name")
 private String lastName;
 @Ignore
 public User(String firstName, String lastName) {
 this.uid = UUID.randomUUID().toString();
 this.firstName = firstName;
 this. lastName = lastName;
 }
 public User(String id, String firstName, String lastName) {
 this.uid = id;
 this.firstName = userName;
 this. lastName = userName;
 }
 // Getters and setters
}
  • @Entity(tableName = "table_name**") 注解POJO类,定义数据表名称;
  • @PrimaryKey 定义主键,如果一个Entity使用的是复合主键,可以通过@Entity注解的primaryKeys 属性定义复合主键:@Entity(primaryKeys = {"firstName", "lastName"})
  • @ColumnInfo(name = “column_name”) 定义数据表中的字段名
  • @Ignore 用于告诉Room需要忽略的字段或方法
  • 建立索引:在@Entity注解的indices属性中添加索引字段。例如:indices = {@Index(value = {"first_name", "last_name"}, unique = true), ...}, unique = true可以确保表中不会出现{"first_name", "last_name"} 相同的数据。

1.2 Entitiy间的关系

不同于目前存在的大多数ORM库,Room不支持Entitiy对象间的直接引用。

但Room允许通过外键(Foreign Key)来表示Entity之间的关系。

@Entity(foreignKeys = @ForeignKey(entity = User.class,
     parentColumns = "id",
     childColumns = "user_id"))
class Book {
 @PrimaryKey
 public int bookId;
 public String title;
 @ColumnInfo(name = "user_id")
 public int userId;
}

如上面代码所示,Book对象与User对象是属于的关系。Book中的user_id,对应User中的id。 那么当一个User对象被删除时, 对应的Book会发生什么呢?

@ForeignKey注解中有两个属性onDelete和onUpdate, 这两个属性对应ForeignKey中的onDelete()和onUpdate(), 通过这两个属性的值来设置当User对象被删除/更新时,Book对象作出的响应。这两个属性的可选值如下:

  • CASCADE:User删除时对应Book一同删除; 更新时,关联的字段一同更新
  • NO_ACTION:User删除时不做任何响应
  • RESTRICT:禁止User的删除/更新。当User删除或更新时,Sqlite会立马报错。
  • SET_NULL:当User删除时, Book中的userId会设为NULL
  • SET_DEFAULT:与SET_NULL类似,当User删除时,Book中的userId会设为默认值

1.3 对象嵌套

在某些情况下, 对于一张表中的数据我们会用多个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表中,Column 为id, firstName, street, state, city, post_code

2. 创建数据访问对象(DAO)

@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(List<User> users);
 @Insert(onConflict = OnConflictStrategy.REPLACE)
 public void insertUsers(User... users);
 @Delete
 void delete(User user);
 @Update
 public void updateUsers(List<User> users);
}

DAO 可以是一个接口,也可以是一个抽象类, Room会在编译时创建DAO的实现。

Tips:

  • @Insert方法也可以定义返回值, 当传入参数仅有一个时返回long, 传入多个时返回long[]或List<Long>, Room在实现insert方法的实现时会在一个事务进行所有参数的插入。
  • @Insert的参数存在冲突时, 可以设置onConflict属性的值来定义冲突的解决策略, 比如代码中定义的是@Insert(onConflict = OnConflictStrategy.REPLACE), 即发生冲突时替换原有数据
  • @Update和@Delete 可以定义int类型返回值,指更新/删除的函数

DAO中的增删改方法的定义都比较简单,这里不展开讨论,下面更多的聊一下查询方法。

2.1 简单的查询

Talk is cheap, 直接show code:

@Query("SELECT * FROM user")
List<User> getAll();

Room会在编译时校验sql语句,如果@Query() 中的sql语句存在语法错误,或者查询的表不存在,Room会在编译时报错。

2.2 查询参数传递

@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);

看代码应该比较好理解, 方法中传递参数arg, 在sql语句中用:arg即可。编译时Room会匹配对应的参数。

如果在传参中没有匹配到:arg对应的参数, Room会在编译时报错。

2.3 查询表中部分字段的信息

在实际某个业务场景中, 我们可能仅关心一个表部分字段的值,这时我仅需要查询关心的列即可。

定义子集的POJO类:

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

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

在DAO中添加查询方法:

@Query("SELECT first_name, last_name FROM user")
public List<NameTuple> loadFullName();

这里定义的POJO也支持使用@Embedded

2.3 查询结果的返回类型

Room中查询操作除了返回POJO对象及其List以外, 还支持:

阅读剩余部分

相关阅读 >>

from csv to Sqlite3 by python 导入csv到Sqlite实例

python操作Sqlite简明教程

Sqlite 入门教程一 基本控制台(终端)命令

适合python项目的五大sql连接器

.net数据库操作框架sqlsugar的简单入门

ios开发中使用sql语句操作数据库的基本用法指南

保护你的Sqlite数据库(Sqlite数据库安全秘籍)

android实现简易记事本

python 连接各类主流数据库的实例代码

mssql和Sqlite中关于if not exists 的写法

更多相关阅读请进入《Sqlite》频道 >>


数据库系统概念 第6版
书籍

数据库系统概念 第6版

机械工业出版社

本书主要讲述了数据模型、基于对象的数据库和XML、数据存储和查询、事务管理、体系结构等方面的内容。



打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

评论

管理员已关闭评论功能...