Android Room DataBase

server/2024/9/20 7:24:12/ 标签: android, 数据库, database

Room数据库是在Sqlite的基础上,进行了封装和优化。这让我们可以摆脱,繁琐的数据库操作

在module的gradle里面,加入:

dependencies {annotationProcessor "androidx.room:room-compiler:2.3.0"implementation 'androidx.room:room-common:2.3.0'implementation 'androidx.room:room-runtime:2.3.0'implementation 'androidx.room:room-runtime:2.3.0'}

一、Room的三大组件

Room的三大组件,换言之,即是Room由哪三个东西组成。

    Entity:每一个Entity是一个类,同时也是一张表。默认情况下,类名即是表名,字段名,即是字段名。可以通过注解的形式,进行自定义表名和字段名,这个在下一篇会详细讲解。
    Dao:每一个Dao,定义了一组对Entity的操作(Method, 即方法)。比如,增删查改。

    DataBase:DataBase类似于Manager,通过DataBase,可以获取到任意有绑定到DataBase的Dao对象,再通过Dao对象,就可以对每一个Entity进行操作。作为一个DataBase类,必须满足以下三个条件:

    1、DataBase类必须是继承自RoomDataBase,并且其本身,必须是抽象类。
    2、通过在头部以注解的方式(后面会讨论如何做),添加一组Entity。这句话的意思是,只要Entity添加在DataBase类的头部,那该DataBase就可以,对已添加的Entity进行操作。
    3、至少包含一个不带参数的抽象方法,该方法返回一个已绑定的Entity所对应的Dao类型。

二、如何定义Entity

每一个Entity类,都会在其类名定义的前一行,增加一个注解@Entity,来标识该类是Room的一个Entity。每一个字段都有一个注解,这里就列举几个比较简单常见的:

1、@PrimaryKey,表示该字段是主键、@NonNull 表示该字段不允许为空。
2、@ColumnInfo(name = “last_name”),表示该字段是表中的一个字段,字段名为自定义的last_name。
3、@Ignore,表示不对字段进行存储。
4、@Entity(tableName ="meals"),实际数据库表名为meals
其他:

5、主键ID的自增(autoGenerate)。只要设置PrimaryKey的autoGenerate属性为true即可

@PrimaryKey(autoGenerate = true)
 private int id;

6、联合主键(primaryKeys)。与单主键不同的是,联合主键的定义,是作为@Entity的属性的形式,被定义的。并且,关键字是primaryKeys,不是primaryKey,多了一个s。代码如下:

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

    public String firstName;
    public String lastName;

    @Ignore
    Bitmap picture;
}

7、创建索引与唯一性约束。

我们可以通过创建索引,来提高查询的效率,其原理是索引原理。同时,可以创建字段的唯一性约束,来避免创建相同的数据。因为在一张表中,除了主键(id)字段的每条数据都是不同之外,有可能还存在其它字段的数据也不允许重复,比如身份证号码,这时就需要添加唯一性约束。

a)、索引(indices)

创建索引的根本目的,是提高查询的效率。那么,如何在Entity中,创建索引呢?

@Entity(indices = {@Index("name"),
        @Index(value = {"last_name", "address"})})
class User {
    @PrimaryKey
    public int id;

    public String firstName;
    public String address;

    @ColumnInfo(name = "last_name")
    public String lastName;

    @Ignore
    Bitmap picture;
}

b)、唯一性约束(unique)

有时候,我们可能想要某一字段,或多个字段的组合的数据,在表中是唯一的,不重复的。那么,我们可以使用唯一性约束。代码如下:

@Entity(indices = {@Index(value = {"first_name", "last_name"},
        unique = true)})
class User {
    @PrimaryKey
    public int id;

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

    @ColumnInfo(name = "last_name")
    public String lastName;

    @Ignore
    Bitmap picture;
}

三、如何定义Dao

@Dao
public interface dishmealDao {@Query("SELECT * FROM meals")List<dishmeal> getAllMeals();// 获取表中记录的数量@Query("SELECT COUNT(*) FROM meals")int getMealsCount();@Query("SELECT * FROM meals")Cursor getMealCursor();@Query("SELECT * FROM meals WHERE MealID=:MealID")dishmeal getMeal(String MealID);@Query("select * from meals where MealID in (:mealids)")List<dishmeal> loadMealsByIds(String[] mealids);@Query("select * from meals where MealName like :first or MealSpell like :last ")//limit 1List<dishmeal> findMealsByName(String first, String last);@Query("SELECT * FROM meals WHERE MealName=:MealName")List<dishmeal> getMealsByName(String MealName);@Query("DELETE FROM meals")int deleteAllMeals();@Query("DELETE FROM meals WHERE MealID=:MealID")int delete(String MealID);@Insertlong insert(dishmeal meal);@Updateint update(dishmeal... meals); //动态根据查询条件,查询@RawQueryList<dishmeal> getMyEntities(SupportSQLiteQuery query);}

每一个Dao类,都会在其类名定义的前一行,增加一个注解@Dao,来标识该类是Room的一个Dao。每一个方法,都有一个注解,用来表示,这个方法能对表进行的操作。这里,同样例举几个常见的注解:

1、@Query,表示查询数据。具体的sql语句写在其后的大括号里面,记得要加上” “双引号。
2、@Insert,表示插入数据。(onConflict = OnConflictStrategy.REPLACE),这段表示,如果插入有冲突,就直接替换掉旧的数据。
3、@Update,表示更新数据。
4、@Delete,表示删除数据


四、如何定义一个DataBase?

@Database(entities = { User.class,dishmeal.class }, version = 2, exportSchema = false)
public abstract class AppDatabase extends RoomDatabase {private static final String DB_NAME = "AppDatabase.db";private static volatile AppDatabase instance;private static Context mContex = null;public static synchronized AppDatabase getInstance(Context context) {mContex = context;if (instance == null) {instance = create(context);}return instance;}private static AppDatabase create(final Context context) {AppDatabase database = Room.databaseBuilder(context,AppDatabase.class,DB_NAME)
//                .addMigrations(MIGRATION_1_2) // , MIGRATION_2_3, MIGRATION_3_4, MIGRATION_1_4).fallbackToDestructiveMigration().build();// 获取数据库文件路径并打印String dbPath = context.getDatabasePath(DB_NAME).getAbsolutePath();Logger.d("Database path: " + dbPath);return database;}public static void Refdatabase(){if (instance!=null) {instance.close();instance = create(mContex);}}//动态设置查询条件public static List<dishmeal> getMealsEntities(QueryFactory queryFactory) {return instance.getmealDao().getMyEntities(queryFactory.createQuery());}public abstract UserDao getUserDao();public abstract dishmealDao getmealDao();}

每一个DataBase类,都会在其类名定义的前一行,增加一个注解@Database,来标识该类是Room的一个Database。其中,entities字段,表示该DataBase,绑定的表。多个表以逗号分开。version字段,表示该DataBase的版本。

五、如何使用他们

先定义 dishmealDao对象dtMeals,再在新线程中调用dishmealDao下的方法

附件:设置动态查询条件

1)、创建接口QueryFactory,
SupportSQLiteQuery是Room数据库库在 SQLite上的抽象,它允许你构建查询并以标准的方式执行它们

public interface QueryFactory {
    SupportSQLiteQuery createQuery();
}

2)、定义MyQueryFactory 重新SupportSQLiteQuery 方法

public class MyQueryFactory implements QueryFactory {private String whereClause;private String[] whereArgs;private String tablename;public MyQueryFactory(String tablename,String whereClause, String[] whereArgs) {this.whereClause = whereClause;this.whereArgs = whereArgs;this.tablename=tablename;}@Overridepublic SupportSQLiteQuery createQuery() {return new SimpleSQLiteQuery("SELECT * FROM   " + tablename + " " + whereClause, whereArgs);}
}

3)、在@Dao里设置动态根据查询条件,查询

@RawQuery List<dishmeal> getMyEntities(SupportSQLiteQuery query);

4)、在class AppDatabase extends RoomDatabase定义:

//动态设置查询条件

public static List<dishmeal> getMealsEntities(QueryFactory queryFactory)
{ return instance.getmealDao().getMyEntities(queryFactory.createQuery()); }

5)、应用例子:

String whereClause =" WHERE MealName like ? or MealID LIKE ? ";
String[] whereArgs = new String[]{"%水%","%2%"};//
QueryFactory queryFactory = new MyQueryFactory("meals",whereClause, whereArgs);
List<dishmeal> mlst= AppDatabase.getInstance(ShowTable.this).getMealsEntities(queryFactory);


http://www.ppmy.cn/server/104965.html

相关文章

python爬虫——入门

一、概念 万维网之所以叫做网&#xff0c;是因为通过点击超链接或者进入URL&#xff0c;我们可以访问任何网络资源&#xff0c;从一个网页跳转到另一个网页&#xff0c;所有的相关资源连接在一起&#xff0c;就形成了一个网。 而爬虫呢&#xff0c;听名字就让人想起来一个黏糊…

[图解]片段16 ESS状态机图-SysMLEA建模住宅安全系统

1 00:00:00,220 --> 00:00:03,580 然后我们看初始这里 2 00:00:03,590 --> 00:00:09,500 有一个指向它的一个迁移的事件 3 00:00:09,710 --> 00:00:13,730 站点可用&#xff0c;这个实际上是错误的 4 00:00:14,020 --> 00:00:15,050 这不是事件 5 00:00:15,900…

【达梦数据库】锁超时的处理方法-错误码[-6407]

【达梦数据库】锁超时的处理方法-错误码[-6407] 链接: https://eco.dameng.com/document/dm/zh-cn/faq/faq-errorcode.html#[-6407]%20%E9%94%81%E8%B6%85%E6%97%B6

《AI办公类工具PPT系列之四——ChatPPT》

一.简介 官网:ChatPPT_AI一键对话生成PPT_智能排版美化-必优科技智能PPT ChatPPT是一款基于人工智能技术的PPT制作工具,它通过对话式AI创作,为用户提供快速生成和美化PPT的全流程服务。 二.功能介绍 1、一键生成PPT 主题输入:用户只需输入PPT的主题,ChatPPT即可根据主…

科技在日常生活中的革新

在科技日新月异的今天&#xff0c;‌我们的生活正经历着前所未有的变革。‌从智能家居到可穿戴设备&#xff0c;‌科技已经渗透到我们生活的每一个角落&#xff0c;‌深刻地影响着我们的生活方式和社会经济的发展。‌ 智能家居系统的出现&#xff0c;‌无疑是科技改变生活的典…

鸿蒙内核源码分析(原子操作篇) | 谁在为原子操作保驾护航

基本概念 在支持多任务的操作系统中&#xff0c;修改一块内存区域的数据需要“读取-修改-写入”三个步骤。然而同一内存区域的数据可能同时被多个任务访问&#xff0c;如果在修改数据的过程中被其他任务打断&#xff0c;就会造成该操作的执行结果无法预知。 使用开关中断的方…

SpringCache操作Redis

目录 &#xff08;一&#xff09;什么是SpringCache? &#xff08;二&#xff09;解决了什么问题&#xff1f; &#xff08;三&#xff09;如何使用SpringCache&#xff1f; &#xff08;一&#xff09;什么是SpringCache? SpringCache是一个由Spring提供的缓存框架&…

Git 版本控制操作

1. 版本回退 Git 能够管理⽂件的历史版本&#xff0c;这是版本控制器重要的能⼒。如果有⼀天你发现之前前的⼯作做的出现了很⼤的问题&#xff0c;需要在某个特定的历史版本重新开始&#xff0c;这个时候&#xff0c;就需要版本回退的功能了。 执⾏ git reset 命令⽤于回退版…

ACCESS 工具注入实战 凡诺靶场

简介 Access数据库注入攻击是一种常见的网络安全&#xff0c;通过注入SQL代码来获取未授权的数据访问权限。这种攻击利用了应用程序与数据库之间的交互漏洞&#xff0c;攻击者通过输入特定的SQL代码片段来操纵数据库查询&#xff0c;从而绕过应用程序的安全机制&#xff0c;获取…

Go Convey测试框架入门(go convey gomonkey)

Go Convey测试框架入门 介绍 GoConvey是一款针对Golang的测试框架&#xff0c;可以管理和运行测试用例&#xff0c;同时提供了丰富的断言函数&#xff0c;并支持很多 Web 界面特性。 Golang虽然自带了单元测试功能&#xff0c;并且在GoConvey框架诞生之前也出现了许多第三方测…

第132天:内网安全-横向移动Exchange服务有账户CVE漏洞无账户口令爆破

域控环境0day.org 通过网盘分享的文件&#xff1a;131-0day.org内网域环境镜像文件 链接: https://pan.baidu.com/s/1rf_gHVJSNG8PEsiSr7DFSw?pwdr5jc 提取码: r5jc 给win7设置一张nat网卡&#xff0c;其他各个主机都设置为vm2 案例一&#xff1a; 域横向移动-内网服务-Exchan…

[kaggle竞赛] 毒蘑菇的二元预测

毒蘑菇的二元预测 您提供了很多关于不同二元分类任务的资源和链接&#xff0c;看起来这些都是Kaggle竞赛中的参考资料和高分解决方案。为了帮助您更好地利用这些资源&#xff0c;这里是一些关键点的总结&#xff1a; Playground Season 4 Episode 8 主要关注的竞赛: 使用银行…

Java ArrayList和LinkedList

ArrayList ArrayList是Java中最常用的数据结构之一&#xff0c;它是一个动态数组的实现&#xff0c;允许你在程序中存储和管理一个可变大小的对象列表&#xff0c;我们可以添加或删除元素。 ArrayList 继承了 AbstractList &#xff0c;并实现了 List 接口。 基本概念 Arra…

Git(面试篇)

目录 配置操作 全局配置 当前仓库配置 查看global配置 查看当前仓库配置 删除global配置 删除当前仓库配置 本地操作 查看变更情况 将当前目录及其子目录下所有变更都加入到暂存区 将仓库内所有变更都加入到暂存区 将指定文件添加到暂存区 比较工作区和暂存区的所有…

JavaScript学习文档(5):为什么需要函数、函数使用、函数传参、函数返回值、作用域、匿名函数、逻辑中断

目录 一、为什么需要函数 1、函数 2、说明 二、函数使用 1、函数的声明语法 2、函数名命名规范 3、函数调用语法 4、函数体 5、函数案例&#xff08;数字求和&#xff09; &#xff08;1&#xff09;计算1-100之间所有数字的和 三、函数传参 1、声明语法 2、调用语…

【Redis】Redis数据结构——List列表

List列表 命令lpushlpushxrpushrpushxlrangelpoprpoplindexlinsertllen 阻塞版本命令blpopbrpop 命令⼩结内部编码使用场景消息队列分频道的消息队列微博 Timeline 列表类型是⽤来存储多个有序的字符串&#xff0c;如图 2-19 所⽰&#xff0c;a、b、c、d、e 五个元素从左到右组…

Java 使用线程池和CountDownLatch分批插入或者更新数据

需求&#xff1a;在开发业务报表时&#xff0c;需要从MySQL数据库读取数据后进行操作&#xff0c;然后写入数据库&#xff0c;使用定时任务跑批。 分析&#xff1a;①兼顾性能&#xff0c;② MySQL没有Oracle那么方便、强大的存储过程。综上所述&#xff0c;使用线程池以分批提…

python dash框架 油气田可视化软件设计文档

V1.1:机器学习框架(神经网络) 时间范围优化 表格布局优化 添加前端设计元素布局 V1.0&#xff1a;基础布局和对应计算函数 要求 首先第一部分是通过神经网络预测天然气流量&#xff0c;其中输入开始时间和截止时间是为了显示这一段时间内的天然气流量预测结果 第二部分&…

前端实现首次访问,后续从本地访问

在前端实现将PDF文件下载到用户的本地磁盘&#xff0c;并在后续加载时使用本地文件&#xff0c;而不是重新从服务器下载&#xff0c;可以通过以下步骤实现&#xff1a; 1. **使用<a>标签的download属性**&#xff1a;当用户首次点击下载PDF时&#xff0c;通过<a>标…

私有仓库tomcat镜像构建

通过Tomcat安装包构建镜像 Dockerfile # 使用官方的OpenJDK镜像作为基础镜像 FROM xa-test.harbor.com:55555/idaas/openjdk:8u232 ENV CATALINA_HOME/usr/local/tomcat ENV PATH$CATALINA_HOME/bin:$PATH # 将Tomcat的压缩包复制到镜像中并解压到指定目录 COPY apache-tomcat…