Room数据库的使用


引用room库
在app build.gradle里面新增下面代码

    //room数据库:这里以2.3.0版本为例
    implementation "androidx.room:room-runtime:2.3.0"
    annotationProcessor "androidx.room:room-compiler:2.3.0"

创建实体类
用@Entity注解来表示一个数据库的表
比如创建一个用户表

@Entity(tableName = "user")
public class UserEntity {

    //主键、自增ID
    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "uid")
    public int uid;
    //@ColumnInfo() 表示数据库表中的字段名称,不写的话默认下面字段为表的字段
    @ColumnInfo(name = "name")
    public String name;

    @ColumnInfo(name = "avatar")
    public String avatar;

    @ColumnInfo(name = "sex")
    public int sex;

    @ColumnInfo(name = "age")
    public int age;

    @ColumnInfo(name = "nick")
    public String nick;
}

Dao层(数据库访问业务操作)
一般就是做CRUD等操作。
@Insert 新增一条数据
@Update 修改一条数据
@Delete 删除一条数据
@Query 查询,里面可以用SQL语法

@Dao
public interface UserDao {

    /**
     * 新增用户;返回当前主键ID
     **/
    @Insert(onConflict = OnConflictStrategy.IGNORE)
    long insertUser(UserEntity userEntity);

    /**
     * 删除用户
     **/
    @Delete
    void delete(UserEntity userEntity);

    /**
     * 修改用户
     **/
    @Update(onConflict = OnConflictStrategy.IGNORE)
    int update(UserEntity userEntity);

    /**
     * 查询所有用户
     */
    @Query("select * from user")
    List<UserEntity> findAll();


    /**
     * 查询用户(根据用户Id)
     **/
    @Query("select * from user where uid=(:userId)")
    UserEntity findUserById(int userId);
}

创建数据库对象
@Database里面的参数说明
entities 表对象集合
version 当前数据库版本
下面的addMigrations里面的内容为升级数据版本做的一些业务操作,仅供参考。

@Database(entities = {UserEntity.class}, version = 7, exportSchema = false)
public abstract class AppDatabase extends RoomDatabase {

    private static volatile AppDatabase mAppDatabase;
    //数据库名
    private static final String DB_NAME = "test.db";

    public static AppDatabase getInstance(Context context) {
        if (mAppDatabase == null) {
            synchronized (AppDatabase.class) {
                if (mAppDatabase == null) {
                    mAppDatabase = Room.databaseBuilder(context.getApplicationContext(),
                            AppDatabase.class, DB_NAME)
                          //仅供参考,实际已业务开发为准。      
                          //.addMigrations(MIGRATION_1_3,MIGRATION_3_4,MIGRATION_4_5,MIGRATION_5_6,MIGRATION_6_7)
                            //上面的addMigrations出现异常会强制升级,将清除表的数据,慎用!!!
                            .fallbackToDestructiveMigration()
                            //允许在主线程连接数据库(默认不允许),如果关闭下面的方法,
                            //需要在子线程进行调用数据库操作。建议在子线程处理耗时操作
//                            .allowMainThreadQueries()
                            .build();

                }
            }
        }
        return mAppDatabase;
    }

    /**新建表**/
    static final Migration MIGRATION_1_3 = new Migration(1,3) {
        @Override
        public void migrate(SupportSQLiteDatabase database) {
            database.execSQL("create table goods(gid integer primary key autoincrement,name text,desc text)");
        }
    };

    /**新建表**/
    static final Migration MIGRATION_3_4 = new Migration(3,4) {
        @Override
        public void migrate(SupportSQLiteDatabase database) {
            database.execSQL("create table student(sid integer primary key autoincrement,name text)");
        }
    };

    /**删除表**/
    static final Migration MIGRATION_4_5 = new Migration(4,5) {
        @Override
        public void migrate(SupportSQLiteDatabase database) {
            database.execSQL("drop table student");
        }
    };

    /**新建表**/
    static final Migration MIGRATION_5_6 = new Migration(5,6) {
        @Override
        public void migrate(SupportSQLiteDatabase database) {
            database.execSQL("create table student(sid integer primary key autoincrement,name text)");
        }
    };

    /**user表新增一列**/
    static final Migration MIGRATION_6_7 = new Migration(6,7) {
        @Override
        public void migrate(SupportSQLiteDatabase database) {
            database.execSQL("alter table user add column nick text NULL");
        }
    };
    
    public abstract UserDao userDao();
}

使用数据库
再Activity里面调用,Activity采用的是Kotlin的代码。
新建Activity的时候忘记选择Java语言了,呜呜!

新增用户

//初始化对象
val appDatabase = AppDatabase.getInstance(this)
//初始化线程池
val threadPool = Executors.newCachedThreadPool()

//新增用户,一般放到按钮点击事件里面即可
threadPool.execute {
           
                val user = UserEntity()
                user.name = "张三"
                user.avatar = "http://wwww.xxxx.jpg"
                user.sex = 1
                user.age = 18
                user.nick = "zhangsan"
               
                val insertUser = appDatabase.userDao().insertUser(user)
                if (insertUser > 0) {
                    Log.i("====", "====insertUser: $insertUser")
                    //这里是切换到主线程进行调用
                    this.runOnUiThread {
                        showToast("新增成功")
                    }
                }
            }

根据用户ID删除用户,参数1为实际业务值,这里仅供参考

threadPool.execute {
                val findUser = appDatabase.userDao().findUserById(1)
                if (findUser != null) {
                    appDatabase.userDao().delete(findUser)
                    //这里是切换到主线程进行调用
                    this.runOnUiThread {
                        //Toast
                        showToast("删除成功")
                    }
                }
            }

根据用户ID修改用户信息,参数1为实际业务值,这里仅供参考

threadPool.execute {
                val findUser = appDatabase.userDao().findUserById(1)
                if (findUser != null) {
                    findUser.name = "测试修改用户名称"
                    val update = appDatabase.userDao().update(findUser)
                    if (update > 0) {
                       //这里是切换到主线程进行调用
                        this.runOnUiThread {    
                            showToast("修改成功")
                        }
                        Log.i("====", "====update: $update")
                    }
                }
            }

查询所有的用户

threadPool.execute {
                val findAll = appDatabase.userDao().findAll()
                //这里是切换到主线程进行调用
                this.runOnUiThread {
                  //我这里是查询到结果放到RecyclerView里面进行展示。
                  //mAdapter.setList(findAll)
                }
            }

附:遇到的问题


1、无法验证数据完整性。看起来您已经更改了架构,但忘记更新版本号。您可以通过增加版本号来解决这个问题。
需要修改version数值
@Database(entities = {UserEntity.class}, version = 7, exportSchema = false)

cannot verify the data integrity. Looks like you've changed schema but forgot to update the version number. You can simply fix this by increasing the version number.


2、无法在主线程上访问数据库,因为它可能会锁定UI很长一段时间。
在子线程里面调用数据库,或者开启 .allowMainThreadQueries()

Caused by: java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.


3、没有找到数据库从版本号1迁移到版本号2的迁移文件。请通过RoomDatabase.Builder.addMigration()方法增加迁移文件,或者RoomDatabase.Builder.fallbackToDestructiveMigration()方法进行处理。

升级需要通过.addMigration 手动升级,现在升级对应的业务(比如新增一列,新增表等)

 java.lang.IllegalStateException: A migration from 1 to 2 was required but not found. Please provide the necessary Migration path via RoomDatabase.Builder.addMigration(Migration ...) or allow for destructive migrations via one of the RoomDatabase.Builder.fallbackToDestructiveMigration* methods.

Room使用教程:https://developer.android.google.cn/training/data-storage/room?hl=zh-cn

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐