Android官方ORM Room介绍

基本使用

  1. 通过实体类和注解定义表数据:
Entitypublic class User {    @PrimaryKey    public int uid;        @ColumnInfo(name = "first_name")    public String firstName;        @ColumnInfo(name = "last_name")    public String lastName;}
  1. 创建具体操作的Dao接口类:
@Daopublic interface UserDao {    @Query("SELECT * FROM user")    List getAll();    @Query("SELECT * FROM user WHERE uid IN (:userIds)")    List 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);}
  1. 定义继承自RoomDatabase的数据库类,在这个类中定义创建Dao类的接口,是抽象类,Room将在编译时生成具体的实现类:
@Database(entities = {User.class}, version = 1)public abstract class AppDatabase extends RoomDatabase {    public abstract UserDao userDao();}
  1. 在代码中使用:
//创建db对象AppDatabase db = Room.databaseBuilder(getApplicationContext(),        AppDatabase.class, "database-name").build();//通过在AppDatabase中定义的接口方法获取Dao对象UserDao userdao = db.userDao();//调用Dao中对应方法执行操作userDao.getAll();

数据定义

在Room中,每个表关联一个使用@Entity注解的实体类,表中的列关联到实体类的字段,表的列的属性通过实体类中注解来实现:

@Entitypublic class User {    @PrimaryKey    public int id;    public String firstName;    public String lastName;}

需要在@Database注解entities属性中声明实体类,Room会在编译时自动生成创建表的代码,并在初始化时创建表:

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

 

  1. 主键
    a. 唯一主键;如上面的代码示例,通过在实体字段上添加@PrimaryKey可以声明该列为主键,@PrimaryKey 注解还包含autoGenerate属性,可以声明主键自动生成如:

    @PrimaryKey(autoGenerate = true)public int id;

    b. 联合主键;当要定义联合主键时可以使用@Entity的属性primaryKeys,如:

    @Entity(primaryKeys = {"firstName", "lastName"}) public class User {     public String firstName;     public String lastName; }

     

  2. 忽略实体字段;一般情况下,实体中所有字段都会在表中创建一个列,当要某些字段不需要创建列时,可以通过添加注解@Ignore将其忽略,如:

    @Entitypublic class User {    @PrimaryKey    public int id;    public String firstName;    public String lastName;    @Ignore    Bitmap picture;}

    也可以通过@Entity的属性ignoredColumns 来将其忽略,如:

    @Entity(ignoredColumns = "picture")public class RemoteUser extends User {    @PrimaryKey    public int id;    public boolean hasVpn;}

     

  3. 查询优化;
    a. 索引;在Room中通过@Entity 的属性indices来建立索引,如:

    @Entity(indices = {@Index("name"),        @Index(value = {"last_name", "address"})})public class User {    @PrimaryKey    public int id;    public String firstName;    public String address;    @ColumnInfo(name = "last_name")    public String lastName;    @Ignore    Bitmap picture;}

    b. 全文检索;SQLite3内置了全文检索的扩展模块——FTS,通过主键@FTS3、@FTS4分别启用基于FTS3和FTS4;如:

    @Fts4@Entity(tableName = "users")public class User {    // Specifying a primary key for an FTS-table-backed entity is optional, but    // if you include one, it must use this type and column name.    @PrimaryKey    @ColumnInfo(name = "rowid")    public int id;    @ColumnInfo(name = "first_name")    public String firstName;}

     

  4. 嵌套对象;有时候,一个表中的几个列在应用逻辑上更适合组合成一个实体,但是为这几个字段单独建表又感觉没必要,Room提供了@Embedded注解来解决这种情况:

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

    在上面例子中,会建立一个包含id、firstName、street、city、state、postCode的User表,而在在查询时street、city、state、postCode会自动组合成Address对象,反之亦然。
     

  5. 视图;通过注解@DatabaseView可以创建视图,如:

    @DatabaseView("SELECT user.id, user.name, user.departmentId," +            "department.name AS departmentName FROM user " +            "INNER JOIN department ON user.departmentId = department.id")public class UserDetail {    public long id;    public String name;    public long departmentId;    public String departmentName;}

    同时,要在@Database中views属性中添加:

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

数据操作

在Room框架中,我们使用DAOs(data access objects)来对数据库中的数据进行操作。可以通过@Dao注解来声明一个Dao类的接口或者抽象类,每个操作对应一个抽象方法,注解@Insert、@Delete、@Update、@Query分别对应增删改查:

@Daopublic interface UserDao {    @Insert    void insertAll(User... users);    @Update    public void updateUsers(User... users);    @Delete    void delete(User user);    @Query("SELECT * FROM user")    List getAll();}

具体实现类会在编译时自动生成,使用时通过在Database类中定义的工厂方法获取:

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

 

  1. 多种方法模板;对于不同的应用场景,Room提供了不同类型的方法:
    @Daopublic interface MyDao {    @Insert(onConflict = OnConflictStrategy.REPLACE)    public void insertUsers(User... users);    @Insert    public void insertBothUsers(User user1, User user2);    @Insert    public void insertUsersAndFriends(User user, List friends);}
    每个方法都可以设置返回值,如果只操作一个数据(只有一个传入参数),则返回一个long型的数据,也就是被操作数据的rowID,如果操作一组数据则返回这一组数据的rowID,返回值应该long[] 或者 List< Long >。
     
  2. 查询参数绑定;Room可以通过:[参数名]的方式将参数注入到SQL查询语句中:
    @Daopublic interface MyDao {    @Query("SELECT * FROM user WHERE age BETWEEN :minAge AND :maxAge")    public User[] loadAllUsersBetweenAges(int minAge, int maxAge);    @Query("SELECT * FROM user WHERE first_name LIKE :search " +           "OR last_name LIKE :search")    public List findUserWithName(String search);}
     
  3. 返回列的子集;在数据库查询结果中经常会只需要某些字段,或者在多表联合查询中需要多张表的字段的情况,这些情况下直接返回定义表的实体对象是不合适的,Room允许你自定义POJO来映射结果集:
    public class NameTuple {    @ColumnInfo(name = "first_name")    public String firstName;    @ColumnInfo(name = "last_name")    public String lastName;}
    @Daopublic interface MyDao {    @Query("SELECT first_name, last_name FROM user")    public List loadFullName();}
     
    Room默认是不允许在UI线程中进行数据操作的,如果要用需要在初始化时调用.allowMainThreadQueries()。基于这种设计哲学,Room对响应式框架非常友好。
     
  4. LiveData;LiveData是Android官方提供的响应式框架,与Room的配合极其简单(Android官方架构工具直接的配合使用都很简洁);在gradle中配置好LiveData相关依赖后,只需要把对应操作的方法返回值用LiveData<>包裹就行了:
    @Daopublic interface MyDao {    @Query("SELECT first_name, last_name FROM user WHERE region IN (:regions)")    public LiveData> loadUsersFromRegionsSync(List regions);}
     
  5. RxJava;Room为不同的操作提供不同的可观察者对象:
    a. 对于@Query,Room提供Publisher、Flowable和Observable;
    b. 对于@Insert、@Update、 @Delete,Room提供Completable、Single和Maybe;
    使用方式也简单:
    首先在app/build.gradle中配置依赖
    dependencies {    implementation 'androidx.room:room-rxjava2:2.1.0-alpha02'}
    然后和LiveData一样用泛型包裹返回值:
    @Daopublic interface MyDao {    @Query("SELECT * from user where id = :id LIMIT 1")    public Flowable loadUserById(int id);    // Emits the number of users added to the database.    @Insert    public Maybe insertLargeNumberOfUsers(List users);    // Makes sure that the operation finishes successfully.    @Insert    public Completable insertLargeNumberOfUsers(User... users);    /* Emits the number of users removed from the database. Always emits at       least one user. */    @Delete    public Single deleteUsers(List users);}
     
  6. 直接返回Cursor;
    @Daopublic interface MyDao {    @Query("SELECT * FROM user WHERE age > :minAge LIMIT 5")    public Cursor loadRawUsersOlderThan(int minAge);}

依赖配置

Room属于官方依赖,提供了AndroidX版本和非AndroidX版本,配置都很简单:

  1. 非AndroidX:
    dependencies {    def room_version = "1.1.1"    implementation "android.arch.persistence.room:runtime:$room_version"    annotationProcessor "android.arch.persistence.room:compiler:$room_version" // use kapt for Kotlin    // 可选- RxJava支持    implementation "android.arch.persistence.room:rxjava2:$room_version"}
  2. AndroidX:
    dependencies {    def room_version = "2.1.0-alpha03"    implementation "androidx.room:room-runtime:$room_version"    annotationProcessor "androidx.room:room-compiler:$room_version" // use kapt for Kotlin    // 可选- RxJava支持    implementation "androidx.room:room-rxjava2:$room_version"}

如果要使用LiveData请参考Lifecycle的配置文档配置LiveData相关依赖。

更多相关文章

  1. android 建数据库 SQLite 存储sd 卡或者内存
  2. 2010.12.08——— android progressDialog
  3. Android应用程序组件Content Provider的共享数据更新通知机制分
  4. 2013.05.16——— android 关于listview的bug
  5. android 数据库 备份还原
  6. xUtils3.3.x注解使用实例
  7. android常用代码片段
  8. Android(安卓)SQLiteOpenHelper(手机数据库)
  9. Android(安卓)ListView SimpleAdapter ArrayList 数据更新问题 z

随机推荐

  1. Android架构分析之JNI
  2. 文件操作与SDCard读写访问
  3. android Fragment添加Theme,使背景模糊
  4. Android framework初识
  5. 多个控件跑马灯效果
  6. android播放音频文件(MediaPlayer)和录音
  7. Android 兼容性测试(CTS)
  8. Android优化和性能
  9. Android进程回收
  10. eclipse中Android布局的基本操作