这是我参与「第四届青训营 」笔记创作活动的第2天
使用Room
添加依赖
def room_version = "2.4.2"
//implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
//implementation 'io.reactivex.rxjava3:rxjava:3.1.4'
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"
// optional - RxJava3 support for Room
implementation "androidx.room:room-rxjava3:$room_version"
简单定义和概览
Room是一个关系映射数据库,ORM (Object Relational Mapping)
构成结构
- Entity
每一个实体对于Room数据库的一个表
每一个实例代表数据库的一行
实例属性代表数据库的列
- Dao
Dao 是数据访问对象的意思。在Dao层封装数据库增删查改地方法。
- Database
用于定义数据库的关键信息,包括数据库的实体类、版本号、以及提供Dao层访问的实例
1:创建实体
@Entity//代表为数据库表
public class User {
@PrimaryKey//定义主键
public int id;
public String firstName;
public String lastName;
}
注意:要保留某个字段,Room 必须拥有该字段的访问权限。您可以通过将某个字段设为公开或为其提供 getter 和 setter 方法,确保 Room 能够访问该字段。
表名和列名的设置
默认情况下,Room 将类名称用作数据库表名称。如果您希望表具有不同的名称,请设置 @Entity 注解的 tableName 属性。同样,Room 默认使用字段名称作为数据库中的列名称。如果您希望列具有不同的名称,请将 @ColumnInfo 注解添加到该字段并设置 name 属性。以下示例演示了表和列的自定义名称:
如果您需要 Room 为实体实例分配自动 ID,请将 @PrimaryKey 的 autoGenerate 属性设为 true。
默认情况下,Room 会为实体中定义的每个字段创建一个列。 如果某个实体中有您不想保留的字段,则可以使用 @Ignore 为这些字段添加注解,如以下代码段所示:
@Entity
public class User {
@PrimaryKey
public int id;
public String firstName;
public String lastName;
@Ignore
Bitmap picture;
}
支持全文搜索(FTS)full text search, 以加快查询速度
以通过将 @Index 注解的 unique 属性设为 true,强制实施此唯一性属性。以下代码示例可防止表格具有包含 firstName 和 lastName 列的同一组值的两行。
// Use `@Fts3` only if your app has strict disk space requirements or if you
// require compatibility with an older SQLite version.
@Fts4
@Entity(indices = {@Index(value = {"first_name", "last_name"},
unique = true)})
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;
}
2:创建数据访问对象
@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);
}
3:数据库对象创建
在实例化
AppDatabase对象时应遵循单例设计模式因为每个RoomDatabase实例的成本相当高
对数据库单例的简单封装
@Database(entities = {User.class},version = 1)//指定版本号和数据库的实体类
public abstract class AppDatabase extends RoomDatabase {
public abstract UserDao userDao();//必须方法
private static AppDatabase instance=null;
public static AppDatabase getInstance(Context context){
if (instance==null){
synchronized (AppDatabase.class) {
if (instance==null) {
instance = Room.databaseBuilder(context, AppDatabase.class, "BDName").build();
//注意第一个参数一定要使用applicationContext,而不能使用普通的
//context,否则容易出现内存泄漏的情况
}
}
}
return instance;
}
}
4:使用
UserDao userDao=AppDatabase.getInstance(getApplicationContext()).userDao();
List<User> all = userDao.getAll();
结合Rxjava
数据库也可以和RXjava 联合在一起使用(room数据库默认不能在主线程操作,但可以修改默认配置)
Room.databaseBuilder(context, AppDatabase.class, "BDName").allowMainThreadQueries().build();//修改可以在主线程进行数据库操作
如果不修改默认配置且在主线程在数据库进行操作
- 在正常情况下程序会crash
- 在和rxjava一起使用时会在onError()方法中回调
User user=new User();
user.setAge(10);
user.setFirstName("h");
user.setLastName("555");
Completable completable=userDao.insertUser(user);
completable.
subscribeOn(Schedulers.io()).
observeOn(AndroidSchedulers.mainThread()).
subscribe(new CompletableObserver() {
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onComplete() {
Log.d("complete", "onComplete: ");
Toast.makeText(MainActivity.this, "success", Toast.LENGTH_SHORT).show();
}
@Override
public void onError(@NonNull Throwable e) {
Toast.makeText(MainActivity.this, e.getLocalizedMessage(), Toast.LENGTH_SHORT).show();
}
});
注意事项
如果想要从数据库中查询数据,或者使用非实体类参数来增删改数据,那么就必须编写 SQL语句
-
删改
Room 使用主键将传递的实体实例与数据库中的行进行匹配。如果没有具有相同主键的行,Room 不会进行任何更改。
若要根据不同的情况也要写query语句
-
增
插入方法的onConflict属性
@Insert(onConflict = OnConflictStrategy.REPLACE)
public void insertUsers(User... users);
如果指定 id 的对象没有保存在数据库中, 就会新增一条数据到数据库。 如果指定 id 的对象数据已经保存到数据库中, 就会删除掉原来的数据, 然后新增一条数据。
-
查
编写SQL语句进行查询
]()
参考 :第一行代码第三版
使用 Room 将数据保存到本地数据库 | Android 开发者 | Android Developers (google.cn)