Android——Jetpack之Room学习(java实现 附demo)

Room是什么

  1. Room是Goole推出的数据库框架,属于ORM库。
    ORM(ObjectRelational Mapping)也叫对象关系映射。简单来讲,我们使用的编程语言是面向对象语言,而使用的数据库则是关系型数据库,将面向对象的语言和面向关系的数据库之间建立一种映射关系,这就是ORM了。
  2. Room是一个持久性数据库。

Room持久性库提供了SQLite的抽象层,以便在充分利用SQLite的同时允许流畅的数据库访问,利用SQlite的全部功能。

  • 优点
    • SQL查询在编译时就会验证 - 在编译时检查每个@Query和@Entity等,这就意味着没有任何运行时错误的风险可能会导致应用程序崩溃(并且它不仅检查语法问题,还会检查是否有该表)
    • 较少的模板代码
    • 与 LiveData集成
    • 与Rxjava结合可以实时监听数据变化

Room组件

  • Entity:数据实体,对应数据库中的表
  • DAO:数据访问对象,提供用于查询、更新、插入和删除数据库中的数据的方法。
  • Database:用于保存数据库并作为应用持久性数据底层连接的主要访问点。

Room架构图
在这里插入图片描述

实现流程

首先实现一个实例,有一个大概的了解,其次分模块学习。

  1. 数据实体(Entity)
    定义了一个 User 数据实体。User 的每个实例都代表应用数据库中 user 表中的一行。
@Entity
public class User {
    
    
    @PrimaryKey
    public int uid;

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

    @ColumnInfo(name = "last_name")
    public String lastName;
}
  1. 数据访问对象 (DAO)
    定义了一个名为 UserDao 的 DAO。UserDao 提供了应用的其余部分用于与 user 表中的数据交互的方法。
@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(User... users);

    @Delete
    void delete(User user);
}
  1. 数据库(Database)

    数据库类必须满足以下条件:

    • 该类必须带有 @Database 注解,该注解包含列出所有与数据库关联的数据实体的 entities 数组。
    • 该类必须是一个抽象类,用于扩展 RoomDatabase
    • 对于与数据库关联的每个 DAO 类,数据库类必须定义一个具有零参

以下代码定义了用于保存数据库的 AppDatabase 类。 AppDatabase 定义数据库配置,并作为应用对持久性数据的主要访问点。
数的抽象方法,并返回 DAO 类的实例。

@Database(entities = {
    
    User.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
    
    
    public abstract UserDao userDao();
}
  1. 用法
    定义数据实体、DAO 和数据库对象后,创建数据库实例:
AppDatabase db = Room.databaseBuilder(getApplicationContext(),
                    AppDatabase.class, "database-name").build();
//使用 AppDatabase 中的抽象方法获取 DAO 的实例
//使用 DAO 实例中的方法与数据库进行交互
UserDao userDao = db.userDao();
List<User> users = userDao.getAll();

使用 Room 实体定义数据

实体详解

  1. 您可以将每个 Room 实体定义为带有 @Entity 注解的类。Room 实体包含数据库中相应表中的每一列的字段,包括构成主键的一个或多个列。

以下代码是一个简单实体的示例,定义了一个 User 表,其中包含 ID 列、名字列和姓氏列:

@Entity
public class User {
    
    
    @PrimaryKey
    public int uid;

    public String firstName;

    public String lastName;
}

注意:要保留某个字段,Room 必须拥有该字段的访问权限。您可以通过将某个字段设为公开或为其提供 getter 和 setter 方法,确保 Room 能够访问该字段。

默认情况下,Room 将类名称用作数据库表名称。如果您希望表具有不同的名称,请设置 @Entity 注解的 tableName 属性。同样,Room 默认使用字段名称作为数据库中的列名称。如果您希望列具有不同的名称,请将 @ColumnInfo 注解添加到该字段并设置 name 属性。

//使用Entity注解的tableName属性:更改数据库表的名称
@Entity(tableName = "users")
public class User {
    
    
    @PrimaryKey
    public int id;

    //使用ColumnInfo提供的name属性:更改数据库中的列名称
    @ColumnInfo(name = "first_name")
    public String firstName;

    @ColumnInfo(name = "last_name")
    public String lastName;
    
    //实现getter,setter方法
    public int getUid() {
    
    
    return uid;
    }
    
    public void setUid(int uid) {
    
    
        this.uid = uid;
    }
    
    public String getFirstname() {
    
    
        return firstname;
    }
    
    public void setFirstname(String firstname) {
    
    
        this.firstname = firstname;
    }
    
    public String getLastname() {
    
    
        return lastname;
    }
    
    public void setLastname(String lastname) {
    
    
        this.lastname = lastname;
    }
}

注意:SQLite中的表和列都不区分大小写。

定义主键

每个 Room 实体都必须定义一个主键,用于唯一标识相应数据库表中的每一行。执行此操作的最直接方式是使用 @PrimaryKey 为单个列添加注解:

@NonNull      //主键不能为空,必须添加该注解
@PrimaryKey(autoGenerate = false)//设置为true,让SQlite生成唯一的ID(即添加一个主键)
public int id;

注意:如果您需要 Room 为实体实例分配自动 ID,请将 @PrimaryKey 的 autoGenerate 属性设为 true。

定义复合主键

通过列出 @Entity 的 primaryKeys 属性中的以下列定义一个复合主键:

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

忽略字段

默认情况下,Room 会为实体中定义的每个字段创建一个列。 如果某个实体中有不想保留的字段,则可以使@Ignore 为这些字段添加注解

@Entity
public class User {
    
    
    @PrimaryKey
    public int id;

    public String firstName;
    public String lastName;

    @Ignore
    public String Name;
    //该字段将被忽略

使用 Room DAO 访问数据

当您使用 Room 持久性库存储应用的数据时,您可以通过定义数据访问对象 (DAO) 与存储的数据进行交互。每个 DAO 都包含一些方法,这些方法提供对应用数据库的抽象访问权限。在编译时,Room 会自动为您定义的 DAO 生成实现。
每个 DAO 定义为一个接口或一个抽象类,但通常应使用接口。无论是哪种情况,都必须始终使用 @Dao 添加注解。DAO 不具有属性,但它们定义了一个或多个方法,可用于与应用数据库中的数据进行交互。

有两种类型的 DAO 方法可以定义数据库交互:

  • 不编写任何 SQL 代码的情况下插入、更新和删除数据库中行的便捷方法。
  • 编写自己的 SQL 查询以与数据库进行交互的查询方法。

不编写SQL 代码的便捷方法

  1. 插入
    借助 @Insert 注释,将其参数插入到数据库中的相应表中的方法。
    a. @Insert方法的每个参数必须是带有@Entity 注解实体类的实例或数据实体类的集合。
    b. 调用方法时,Room 会将每个传递的实体实例插入到相应的数据库表中。
    c. 如果 @Insert 方法接收单个参数,则会返回long 值,这是插入项的新 rowId
    d. 如果参数是数组或集合,则该方法应改为返回由 long 值组成的数组或集合,并且每个值都作为其中一个插入项的 rowId
@Dao
public interface UserDao {
    
    
    //实现一个或多个User对象插入数据库
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    public void insertUsers(User... users);

    @Insert
    public void insertBothUsers(User user1, User user2);

    @Insert
    public void insertUsersAndFriends(User user, List<User> friends);
}
  1. 更新/删除
    借助 @Update/ @Delete注释,定义更新数据库表中特定行的方法。
    a. Room 使用主键将传递的实体实例与数据库中的行进行匹配。如果没有具有相同主键的行, Room 不会进行任何更改。
    b. @Update/ @Delete方法可以选择性的返回 int 值,该值指示成功更新的行数。
@Dao
public interface UserDao {
    
    
    //更新
    @Update
    public void updateUsers(User... users);
    //删除
    @Delete
    public void deleteUsers(User... users);
}

编写 SQL 代码的查询方法

使用 @Query 注解,您可以编写 SQL 语句并将其作为 DAO 方法公开。使用这些查询方法从应用的数据库查询数据,或者需要执行更复杂的插入、更新和删除操作。
Room 会在编译时验证 SQL 查询。这意味着,如果查询出现问题,则会出现编译错误,而不是运行时失败。

  • 使用Room写SQL引用查询条件的格式是“字段名称=:引用值
//使用简单的 SELECT 查询返回数据库中的所有 User 对象:
//SQLite中的表和列都不区分大小写。
@Query("SELECT * FROM user")
public User[] loadAllUsers();

//查询指定first_name的数据
@Query("SELECT * FROM user where first_name =: name")
 public User loadUsers_first();
 
 //查询指定last_name的数据
@Query("SELECT * FROM user where last_name =: name")
 public User loadUsers_last();
 
 
//删除所有 User 对象:
@Query("DELETE * FROM user")
public void deleteAllUsers();

//删除指定first_name的数据
@Query("DELETE * FROM user where first_name =: name")
public void loadUsers_first();

demo地址

https://github.com/Mike-Shake/Demo_zujian/tree/master/room_demo2

猜你喜欢

转载自blog.csdn.net/The_onion/article/details/128066517