当前位置:   article > 正文

Android Room数据使用_room数据库

room数据库

一:Room数据库

       Room 是 Android 提供的一个持久性库,用于在 SQLite 数据库之上提供更高级的抽象层。它旨在简化数据库操作并提供更强大的功能,同时结合了 SQLite 的强大特性。

Room 提供了许多优点:

  • 类型安全: Room 在编译时会检查 SQL 查询的语法,并提供类型安全性。如果查询中有错误,编译器会在编译时发出警告或错误。
  • 方便易用: 提供了简洁的 API,使得数据库操作更加简单、直观,不需要手动编写大量的 SQL 语句。
  • 自动化: 可以轻松地执行常见的数据库操作,如插入、更新、删除等,并且可以通过注解自动生成数据库的实现代码。

Room 由三个主要组件组成:

1.Entity(实体): 表示数据库中的表结构。每个 Entity 对应于数据库中的一张表,并且通过注解来定义。Entity 包含表中的字段以及与数据库中的行对应的数据。

2.DAO(Data Access Object,数据访问对象): 提供数据库操作的方法。通过在 DAO 中定义 SQL 查询或操作方法,并使用注解来标识这些方法,Room 可以在编译时为这些方法生成相应的实现。 

3. Database(数据库): 是数据库的抽象层,它包含数据库的持有者并提供连接的主要访问点。Database 类应该是抽象类并继承自 RoomDatabase。它通常是一个单例,用于获取 DAO 实例并执行数据库操作。

 二:Room使用

官方文档:https://developer.android.com/training/data-storage/room?hl=zh-cn#groovy

1.引入Room java引入 

在app的build.gradle中添加依赖:

def room_version = "2.4.2"
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"
// optional - RxJava2 support for Room
implementation "androidx.room:room-rxjava2:$room_version"
 2.配置编译器选项(可选)

android {
    ...
    defaultConfig {
        ...
        javaCompileOptions {
            annotationProcessorOptions {
                arguments += [
                    "room.schemaLocation":"$projectDir/schemas".toString(),
                    "room.incremental":"true",
                    "room.expandProjection":"true"]
            }
        }
    }
}

1. "room.schemaLocation":"$projectDir/schemas".toString(): 的作用是将配置并启把据库架构导出json文件到指定目录。
2."room.incremental":"true":启用 Gradle 增量注解处理器。
3."room.expandProjection":"true": 配置 Room 以重写查询,使其顶部星形投影在展开后仅包含 DAO 方法返回类型中定义的列。
如果配置了schemaLocation,编译后,会在对应路径生成schemas文件夹,json包含了各个版本的概要,表结构等信息:

3.创建Entity(表)
@Entity(tableName = "user",primaryKeys = {"deviceId", "themeId"})
public class User {
    @NonNull
    public String deviceId;//主键--设备id
    @ColumnInfo
    public long themeId;//主键
    @ColumnInfo
    public String options;
    @ColumnInfo
    public long createdAt;
    @ColumnInfo
    public long updatedAt;
    @ColumnInfo
    public String userName;
}

创建表一般会用到下面几个注解:
@Entity(tableName=“表名称”): @Entity表示定义数据库中的一个表,通常Room会使用类名作为数据库的表名,如果你希望自定义表名可以配置@Entity(tableName = “user”),注意:SQLite中,表名是不区分大小写的。

@PrimaryKey(autoGenerate=true): 定义主键 autoGenerate 用于设置主键自增,默认为false。

@ColumnInfo(name = “别名”): Room默认用变量名称作为数据库表的字段名称,如果你希望字段名称和变量名称不一样,则需要给变量添加@ColumnInfo注解。

@Ignore: 忽略该字段,加上该注解不会将该字段映射到数据库中去。

索引和唯一性:根据操作数据的方式可能需要通过索引来提高查询数据库的速度,通过@Entity添加indices属性,有些字段设置唯一性,可以通过@Index注解下设置unique为true。


@Entity(indices = [Index(value =["deviceId"], unique = true)]) 

4.创建Dao(表操作) 主要用于操作Entity表的增删改查。
@Dao
public interface UserDao {
    @Insert
    void insertUsers(User... users);
    @Delete
    void deleteUsers(User... users);
    @Update
    void updateUsers(User... users);
    @Query("select * from user")
    List<User> getAllUsers();
    @Query("select * from user where deviceId in (:deviceIds)")
    List<User> getAllUsersByDeviceId(String[] deviceIds);
    @Query("select * from user where deviceId = :deviceId limit 1")
    User getUserByDeviceId(String deviceId);
    @Query("select * from user where deviceId = :deviceId and themeId = :themeId")
    User getUser(String deviceId,long themeId);
}

Room 使用注解处理器映射了数据库的增删改查,即 @Insert@Delete@Update@Query 代表我们常用的插入、删除、更新、查询数据库操作。

@Query非常的强大,你可以编写任意sql语句并得到你想要的结果。

5.创建DataBase类(管理表)
使用 @Database 注解的类应满足以下条件:

是一个继承于RoomDatabase 的抽象类。
在注解中包括与数据库相关联的实体列表。
包含一个没有参数的抽象方法并且返回一个带有注解的@Dao。
在运行时,我们可以通过调用 Room.databaseBuilder()或 Room.inMemoryDatabaseBuilder()
来获取 Database 的实例。

@Database(entities = {User.class, VoteStatistics.class, CountOptions.class,
        VoteTheme.class},version = 3,autoMigrations = {@AutoMigration(from = 1, to = 2),@AutoMigration(from = 2, to = 3)})
public abstract class AppDatabase extends RoomDatabase {
    public abstract UserDao getUserDao();
    public static final Migration MIGRATION_1_2 = new Migration(1, 2) {
        @Override
        public void migrate(@NonNull SupportSQLiteDatabase database) {
            //执行升级相关操作
            database.execSQL("DROP TABLE IF EXISTS user");
        }
    };
    public static final Migration MIGRATION_2_3 = new Migration(2, 3) {
        @Override
        public void migrate(@NonNull SupportSQLiteDatabase database) {
            //执行升级相关操作
            database.execSQL("ALTER TABLE vote_theme ADD testId INTEGER Default 0 not null");
        }
    };
}

 @Database 表示继承自RoomDatabase的抽象类,entities指定Entities表的实现类,version指定了DB版本。
必须提供获取DAO接口的抽象方法,比如上面定义的getUserDao(),RoomDatabase将通过这个方法实例化DAO接口。

 public class DatabaseManager {
    private AppDatabase db;
    public DatabaseManager() {
        //context可用applicationcontext代替
        db = Room.databaseBuilder(MyApplication.getInstance(), AppDatabase.class, "voter.db")
                .build();
    }
    public List<User> getAllUsers() {
        UserDao userDao = db.getUserDao();
        return userDao.getAllUsers();
    }
    public void addUser(User user) {
        UserDao userDao = db.getUserDao();
        User result = userDao.getUserByDeviceId(user.deviceId);
        if (result == null) {
            userDao.insertUsers(user);
        } else {
            userDao.updateUsers(user);
        }
    }
    public void deleteUser(User user) {
        UserDao userDao = db.getUserDao();
        userDao.deleteUsers(user);
    }
}

RoomDatabase实例的内存开销较大,建议使用单例模式管理。
点击Build编译项目,Room会自动生成对应的_Impl实现类,此处将生成AppRoomDataBase_Impl.java文件。 

6.AppDatabase 构造数据库之前 build 提供了很多功能的 API 给我们调用,其中包含一些相当重要的 API。
1.addCallback:数据库创建、打开、破坏性迁移的回调
db = Room.databaseBuilder(MyApplication.getInstance(), AppDatabase.class, "voter.db")
        .addCallback(new RoomDatabase.Callback() {
            @Override
            public void onCreate(@NonNull SupportSQLiteDatabase db) {
                super.onCreate(db);
            }
            @Override
            public void onOpen(@NonNull SupportSQLiteDatabase db) {
                super.onOpen(db);
            }
            @Override
            public void onDestructiveMigration(@NonNull SupportSQLiteDatabase db) {
                super.onDestructiveMigration(db);
            }
        })
        .build();

 比如:可通过该方式 在open回调中,在数据库打开时设置同步模式,该方法会保证数据库操作数据同步写入本地磁盘,防止部分机型在断电等情况下数据未及时写入本地数据库导致数据丢失。

  db = Room.databaseBuilder(MyApplication.getInstance(), AppDatabase.class, "voter.db")
//                .addMigrations(MIGRATION_1_2)
                .addCallback(new RoomDatabase.Callback() {
                    @Override
                    public void onCreate(@NonNull SupportSQLiteDatabase db) {
                        super.onCreate(db);
                    }
                    @Override
                    public void onOpen(@NonNull SupportSQLiteDatabase db) {
                        super.onOpen(db);
                        // 在数据库打开时设置同步模式
                        db.execSQL("PRAGMA synchronous = FULL;"); // 设置同步模式为OFF
                    }

                    @Override
                    public void onDestructiveMigration(@NonNull SupportSQLiteDatabase db) {
                        super.onDestructiveMigration(db);
                    }
                })
                .build();
2.addMigrations 数据库迁移
db = Room.databaseBuilder(MyApplication.getInstance(), AppDatabase.class, "voter.db")
        .addMigrations(MIGRATION_1_2)
        .build();
3. addTypeConverter 添加非基本数据类型的数据库转换器,例如 long 转 date
4.allowMainThreadQueries 允许主线程访问数据库
5.createFromAsset().createFromFile()  允许通过其他方式文件、流预填充数据库
6.enableMultiInstanceInvalidation 

如果您的应用在多个进程中运行,请在数据库构建器调用中包enableMultiInstanceInvalidation()。这样,如果您在每个进程中都有一个 AppDatabase 实例,就可以在一个进程中使共享数据库文件失效,并且这种失效会自动传播到其他进程中的 AppDatabase 实例,默认不开启。

7.fallbackToDestructiveMigration 数据库重建

不提供数据库迁移,又不想引发 crash 。但是注意数据会丢失删除数据库重建

8.fallbackToDestructiveMigrationOnDowngrade 数据库重建

如果您仅在从较高数据库版本迁移到较低数据库版本时才希望 Room 回退到破坏性重新创建,请用该方法

9.openHelperFactory 设置数据库的工厂类

设置数据库的工厂类,如果没有设置。则默认使用内置的 FrameworkSQLiteOpenHelperFactory

10. setAutoCloseTimeout 自动关闭策略

启用一个数据库打开后空闲没有使用资源的自动关闭策略

11.setJournalMode 设置数据库的日志模式

设置数据库的日志模式,如果使用内存数据库构建请忽略此值

12.setQueryCallback

每当数据库执行查询操作时候回调,不建议在生产环境使用

13.setQueryExecutor 设置查询的线程池

设置查询的线程池一般不需要设置,会使用默认的 ArchTaskExecutor 内置线程池

14.setTransactionExecutor 设置事务线程池

设置事务线程池一般不需要设置,会使用查询方法的默认线程池,详可见源码 RoomDatabase.java#build()

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/寸_铁/article/detail/785655
推荐阅读
相关标签
  

闽ICP备14008679号