• 转 Android Room数据库使用


    Room使用介绍
    1.创建Database
    Database包含数据库的持有者。
    作为一个数据库的管理类,必须用注解 @Database 标注,并且满足以下条件:

    必须是一个抽象类,并且继承 RoomDatabase。
    在 Database 的注解内,必须包含一个或者多个和数据库关联的实体类。
    包含一个或多个有0个参数的抽象方法,这些方法返回与之关联实体的Dao对象。
    2.创建Entity
    代表数据库关联的一个表

    3.创建Dao
    包含可以访问数据的方法。

    Room使用具体分解:
    步骤1、创建数据库database有两种方式
    方式一:Room.inMemoryDatabaseBuilder

    //创建一个内存数据库
    //但是这种数据库的数据只存在于内存中,也就是进程被杀之后,数据随之丢失
    Room.inMemoryDatabaseBuilder(AppGlobals.getApplication(), CacheDatabase.class);
    方式二:Room.databaseBuilder,通常使用这种方式创建数据库

    Room.databaseBuilder(AppGlobals.getApplication(), CacheDatabase.class, "ppjoke_cache")
    //是否允许在主线程进行查询
    .allowMainThreadQueries()
    //数据库创建和打开后的回调
    //.addCallback()
    //设置查询的线程池
    //.setQueryExecutor()
    //.openHelperFactory()
    //room的日志模式
    //.setJournalMode()
    //数据库升级异常之后的回滚
    //.fallbackToDestructiveMigration()
    //数据库升级异常后根据指定版本进行回滚
    //.fallbackToDestructiveMigrationFrom()
    // .addMigrations(CacheDatabase.sMigration)
    .build();
    创建好数据库后需要添加注解:

    @Database(entities = {Cache.class}, version = 1, exportSchema = true)
    extities:是数据库中有哪些表,映射为java中的JavaBean对象,如果有更多的表,则在后面继续拼接更多的JavaBean即可;
    version:是后续数据库的升级时,比较这个字段
    exportSchema:这个字段默认为true,它会导出一个json文件,包含了数据库在升级或者操作数据表时候的所有的操作,也包含了所有表中的字段,以及字段的描述生成到项目的目录下,这里需要配置下,以便告诉程序生成文件的路径:
    javaCompileOptions{
    annotationProcessorOptions{
    arguments=["room.schemaLocation":"$projectDir/schemas".toString()]
    }
    }

    数据库迁移:

    创建一个migration对象:

    static Migration sMigration = new Migration(1, 3) {
    @Override
    public void migrate(@NonNull SupportSQLiteDatabase database) {
    database.execSQL("alter table teacher rename to student");
    database.execSQL("alter table teacher add column teacher_age INTEGER NOT NULL default 0");
    }
    };
    将该对象添加到database数据库中,

    Room.databaseBuilder(AppGlobals.getApplication(), CacheDatabase.class, "ppjoke_cache")
    .addMigrations(CacheDatabase.sMigration)
    .build();
    步骤2、创建数表Entity
    创建数据表Room为我们提供了很多的注解,所有注解的使用如下:

    import java.io.Serializable;

    import androidx.annotation.NonNull;
    import androidx.room.Entity;
    import androidx.room.PrimaryKey;

    @Entity(tableName = "cache" //表名
    // , indices = {@Index(value = "key", unique = false)}//本表索引,用于大量数据的查询优化,unique有时候需要保证数据表的某个或者某些字段只有唯一的记录,可以通过设置@Index注解的unique属性实现。以下实例代码实现了避免有两条记录包含一样的key值。
    // , inheritSuperIndices = false//如果 该值为true,那么父类中标记的indices{}索引也会算作该表的索引
    // , primaryKeys = {"key"}//主键,一些策略逻辑会用到,比如插入一条数据时如果已存在,则更新否则算新的插入,那么怎么判断 ,数据库中是否已存在该条数据呢?就判断提供的主键,在表中是否已存在
    // , foreignKeys = {
    //外键,一般用于多表数据查询.可以配置多个外键
    //ForeignKey用来设置关联表数据更新时所进行的操作,比如可以在@ForeignKey注解中设置onDelete=CASCADE,这样当Cache表中某个对应记录被删除时,ForeignTable表的所有相关记录也会被删除掉。
    //对于@Insert(OnConflict=REPLACE)注解,SQLite是进行REMOVE和REPLACE操作,而不是UPDATE操作,这个可能影响到foreign key的约束。
    //value:关联查询的表的Java.class,这里给定ForeignTable.class
    //parentColumns:与之关联表ForeignTable表中的列名
    //childColumns:本表的列的名称,必须要和parentColumns个数一致。这两个可以理解为根据cache表中的那个字段去比对ForeignTable表中的那个字段,认为是有关联关系的数据。
    //onDelete:关联表中某条记录被delete或update时,本表应该怎么做:
    // NO_ACTION:什么也不做,
    // RESTRICT:本表跟parentColumns有关系的数据会立刻删除或更新,但不允许一对多的关系,
    // SET_NULL:本表所跟parentColumns有关系的数据被设置为null值,
    // SET_DEFAULT:本表所有跟parentColumns有关系的数据被设置为默认值,也是null值
    // CASCADE:本表所有跟parentColumns有关系的数据一同被删除或更新
    //onUpdate:本表中某条记录被更新时,与之关联的表应该怎么做
    //deferred:本表某条记录变更时,与之关联表的数据变更是否要立即执行,还是等待本表事务处理完再来处理关联表。默认是同时处理。
    // @ForeignKey(value = ForeignTable.class,
    // parentColumns = "foreign_key",
    // childColumns = "key",
    // onDelete = 1,
    // onUpdate = 1,
    // deferred = false)}
    //本表中 那些字段 不需要 映射到表中
    // , ignoredColumns = {"data"}
    )
    public class Cache implements Serializable {
    //PrimaryKey 必须要有,且不为空,autoGenerate 主键的值是否由Room自动生成,默认false
    @PrimaryKey(autoGenerate = false)
    @NonNull
    public String key;

    @ColumnInfo(name = "_data"),指定该字段在表中的列的名字
    public byte[] data;

    @Embedded 对象嵌套,ForeignTable对象中所有字段 也都会被映射到cache表中,
    //同时也支持ForeignTable 内部还有嵌套对象
    public ForeignTable foreignTable;

    }

    public class ForeignTable implements Serializable {
    @PrimaryKey
    @NonNull
    public String foreign_key;

    //@ColumnInfo(name = "_data")
    public byte[] foreign_data;
    }
    下面一个一个分析下这些注解的作用:

    1、@Entity(tableName = "cache")注解,用于将一个java对象映射为数据库表的注解

    2、@PrimaryKeys = {"key"}//主键,一些策略逻辑会用到,比如插入一条数据时如果已存在,则更新否则算新的插入,那么怎么判断 ,数据库中是否已存在该条数据呢?就判断提供的主键,在表中是否已存在

    3、@ForeignKeys = {} 外键

    一般用于多表数据查询.可以配置多个外键,ForeignKey用来设置关联表数据更新时所进行的操作,比如可以在@ForeignKey注解中设置onDelete=CASCADE,这样当Cache表中某个对应记录被删除时,ForeignTable表的所有相关记录也会被删除掉。

    4、indices = {@Index(value = "key", unique = false)}

    本表索引,用于大量数据的查询优化,unique有时候需要保证数据表的某个或者某些字段只有唯一的记录,可以通过设置@Index注解的unique属性实现。以下实例代码实现了避免有两条记录包含一样的key值。

    5、inheritSuperIndices = false,如果该值为true,那么父类中标记的indices{}索引也会算作该表的索引

    6、@ColumnInfo(name = "_data"),指定该字段在表中的列的名字

    //@ColumnInfo(name = "_data"),指定该字段在表中的列的名字
    public byte[] data;
    如果不添加这个columnInfo注解,那么就会以这个字段data作为列名,添加后则以你所指定的_data作为列名。

    7、@Embedded 将其他对象嵌套到表中,

    例如另外一个ForeignTable对象中所有字段需要被映射到cache表中,同时也支持ForeignTable内部还有嵌套对象

    步骤3、创建Dao操作数据表
    对数据表进行增删改查的操作,

    import androidx.room.Dao;
    import androidx.room.Delete;
    import androidx.room.Insert;
    import androidx.room.OnConflictStrategy;
    import androidx.room.Query;
    import androidx.room.Update;

    @Dao
    public interface CacheDao {
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    long save(Cache cache);

    /**
    * 注意,冒号后面必须紧跟参数名,中间不能有空格。大于小于号和冒号中间是有空格的。
    * select *from cache where【表中列名】 =:【参数名】------>等于
    * where 【表中列名】 < :【参数名】 小于
    * where 【表中列名】 between :【参数名1】 and :【参数2】------->这个区间
    * where 【表中列名】like :参数名----->模糊查询
    * where 【表中列名】 in (:【参数名集合】)---->查询符合集合内指定字段值的记录
    *
    * @param key
    * @return
    */

    //如果是一对多,这里可以写List<Cache>
    @Query("select *from cache where `key`=:key")
    Cache getCache(String key);

    //只能传递对象昂,删除时根据Cache中的主键 来比对的
    @Delete
    int delete(Cache cache);

    //只能传递对象昂,删除时根据Cache中的主键 来比对的
    @Update(onConflict = OnConflictStrategy.REPLACE)
    int update(Cache cache);
    }
    其中@Insert和@Update注解后面都有冲突处理onConflict = OnConflictStrategy.REPLACE,也即发生字段更新或者插入冲突时,该如何操作,提供给我们是替换还是回滚、中断、失败、还是忽略冲突等多种选择。
    ————————————————
    版权声明:本文为CSDN博主「沙漠一只雕得儿得儿」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/cpcpcp123/article/details/113575155

  • 相关阅读:
    Vue(三十三)国际化解决方案
    Vue(三十二)SSR服务端渲染Nuxt.js
    字符串与数组常用的属性和方法
    Vue(三十一)轮播组件
    Vue(三十)公共组件
    Vue(二十九)页面加载过慢问题
    Vue(二十八)el-cascader 动态加载
    Vue(二十七)当前GitHub上排名前十的热门Vue项目(转载)
    React(九)create-react-app创建项目 + 按需加载Ant Design
    React(八)样式及CSS模块化
  • 原文地址:https://www.cnblogs.com/mwl523/p/15891735.html
Copyright © 2020-2023  润新知