它通过编译时的SQL验证和注解,让开发者能够更安全、更高效地使用SQLite。一、为什么选择Room?...")suspendfungetUserCount():Int2.返回自定义对象查询结果可以映射到非实体类的数据类。...(@TypeConverter)将复杂对象(如Date,ListString>,自定义对象)存储为数据库支持的类型(如Long,String)。...从定义实体、DAO到构建数据库,整个过程清晰、类型安全。结合协程、LiveData和Flow,可以构建出响应迅速、用户体验良好的应用。精通Room的关键在于:熟练掌握@Query的各种用法。...灵活运用LiveData和Flow实现响应式UI。掌握数据库迁移和类型转换器。遵循最佳实践,编写高效、可靠的数据库代码。
,它可以返回一个long,代表新插入元素的rowId //如果参数是一个数组或者集合,那么应该返回long[]或者List。...@Insert long insert(Student student); //可以返回一个int类型的值,表示从数据库中被删除的行数,虽然通常并没有这个必要 @Delete...+ " = :id") int deleteById(long id); //返回一个int类型的值,表示更新影响的行数,虽然通常并没有这个必要 @Update...类型转换器 Room内置了原始类型。但是,有时你会希望使用自定义数据类型。 要为自定义类型添加这种支持,可以提供一个TypeConverter,它将一个自定义类转换为Room保留的已知类型。...这样就可以直观的看到数据库有没有更改成功~ 从原生sqlite到room的迁移 和room不同版本的迁移没什么区别,毕竟本质上都是对sqlite的操作,但是同样要注意版本号的问题。
,他会返回一个新插入行的 long类型的 rowid。...如果参数是 一个数组和集合就会返回一个long类型的数组或集合。...使用 RxJava 进行响应查询 Room还可以从定义的查询中返回 RxJava2 的 Publisher 和 Flowable 对象。...这里会解释为什么不支持对象引用和怎么使用类型转换器。 使用类型转换器 有时候你想存储自定义的数据类型在数据库的单个列中。...这就需要为自定义类型添加一个类型转换器,这个转换器会将自定类型转换为Room能够认识的原始类型。
基本查询最基本的查询方式是使用 query 方法,该方法允许你指定要查询的内容提供者 URI、需要返回的列、选择条件等参数。...使用LiveData和Room进行响应式查询随着Android架构组件的发展,LiveData 和 Room 成为了现代Android应用中的常用工具。...每种方式都有其适用场景,开发者可以根据实际需求选择合适的方法在Android开发中,ContentResolver 是一个非常重要的组件,它用于访问和操作由内容提供者(Content Provider...= null) { cursor.close(); } }}以上三个示例展示了如何使用 ContentResolver 进行不同类型的数据查询。...+ " ASC";// 定义分页参数(从第0条记录开始,取10条记录)int limit = 10;int offset = 0;// 构建完整的分页查询String limitClause = offset
Room数据库概述Room 是SQLite的一个抽象层,解决了原生SQLite操作繁琐、易出错的问题。通过编译时检查、注解处理、数据访问对象(DAO)等机制,帮助开发者轻松管理和操作数据库。...val firstName: String, val lastName: String, val age: Int)在User实体类中,id是主键,通过@PrimaryKey注解指定,autoGenerate...• getAllUsers通过@Query注解,执行一个SQL查询,获取数据库中的所有用户,返回一个Flow>,可以用于实时监听数据变化。...注意: • @Query注解用于执行自定义SQL查询。 • @Insert、@Update和@Delete注解用于增删改操作,Room会自动生成相应的SQL。2.3....• abstract fun userDao()方法返回UserDao,通过它可以访问用户相关的数据库操作。3. Room数据库的上手指南我演示如何在Demo中集成和使用Room数据库。3.1.
Room Database ObjectBox是非SQLite的ORM数据库框架,它自定义了自己的数据库文件,它的文件只有官方提供的工具才能打开,并且对于外键、主键等支持也比较完备,并且效率比Room...每个Entity需要定义至少一个PrimaryKey,也可以通过一个integer类型的Id定义@PrimaryKey(autoGenerate = true)自动生成Id 为了提升查询的速度,可以通过...PrimaryKey匹配进行操作的 Query操作可以返回Cursor,LiveData Query的参数也可以是一个List对象, @Dao public interface UserDataDao...升级到2,UserData的userAge字段从String变成了int,则需要使用ALTER修改表结构 database.execSQL("ALTER TABLE user_table...UserDatabase_Impl文件中可以看到表和索引都会在数据库创建的时候创建表。 ?
总而言之, Room功能强大,速度和稳定性不弱,还简单易用,算得上是一个优秀的数据库。 这里总结下使用room数据库的过程和遇到的问题,以及如何稳定的进行数据库的迁移和升级。...使用主键 : 一个Entry中至少需要一个主键,使用@PrimaryKey来注释. 自增类型的主键,则可以设置 @PrimaryKey 的 autoGenerate 属性。...= null } 第二步,在dao包里写对应的dao,对应的操作, 注意这些操作接口最好都带个返回值,比如insert返回long,delete返回Int。因为最终的使用总要对操作结果来个判断吧。...:Int // 改 @Update fun update(vararg users: User): Int @Query("DELETE FROM User")...fun deleteAllUser() @Query("SELECT COUNT(*) FROM User") fun countAll():Int } Insert还可以开启个对冲突的策略
前言 Google终于发布了一个和SQLite相关的库了???。之前一直都是在SQLite、XUtils、greenDao、Realm这些数据库之间来回折腾。现在终于有一个更“正统”数据库了。...Room是什么? Room是一个持久性数据库。 Room持久性库提供了SQLite的抽象层,以便在充分利用SQLite的同时允许流畅的数据库访问。 为什么会选择Room?...因为Room有下面几个优点: ① SQL查询在编译时就会验证 - 在编译时检查每个@Query和@Entity等,这就意味着没有任何运行时错误的风险可能会导致应用程序崩溃(并且它不仅检查语法问题,还会检查是否有该表...DAO代表数据访问对象,所以它是告诉我们的数据库如何操作数据的一种方式: @Dao public interface UserDao { @Query("SELECT * FROM user")...也可以返回多种不同的类型。
从 Room 2.2 的稳定版开始,我们可利用一个 @Relation 注解来支持表之间所有可能出现的关系: 一对一、一对多和多对多。 一对一关系 ?...现在,要展示狗和主人的列表,我们需要创建一个新的类来进行建模: data class OwnerWithDogs( val owner: Owner, val dogs: List选择并返回正确的数据类: @Transaction @Query("SELECT * FROM Owner") fun getOwnersWithDogs()...: List 更高阶的数据库关系用例 当使用 @Relation 注解时,Room 会默认从所修饰的属性类型推断出要使用的数据库实体。...如果您想让该查询返回一个不同的类,比如 Pup 这样不是一个数据库实体但是包含了一些字段的对象。
然后,应用使用每个 DAO 从数据库中获取实体,然后再将对这些实体的所有更改保存回数据库中。 最后,应用使用实体来获取和设置与数据库中的表列相对应的值。Room架构图如图所示。...DAO可以是接口,也可以是抽象类,如果是抽象类,则该DAO可以选择有一个以RoomDatabase为唯一参数的构造函数。Room 会在编译时创建每个 DAO 实现。在DAO文件上方添加@DAO注解。...//在Database中添加获取DAO的抽象实例 public abstract CacheDao getCache(); //返回 long,这是插入项的新 rowId。...long rowID = StudentDatabase.getInstance().getCache().save(cache); //返回int,这是删除的行数,更新返回也是int,代表更新的行数...主要包含以下几个步骤: 创建一张和修改的表同数据结构的临时表。 将数据从修改的表复制到临时表中。 删除要修改的表。 将临时表重命名为修改的表名。
“@Entity”注解,表示该类是Room专用的数据类型,对应的表名称也叫BookInfo。...private double price; // 价格 // 以下省略各属性的set***方法和get***方法 } 二、编写书籍信息表对应的持久化类 所谓持久化,指的是将数据保存到磁盘而非内存...BookDao bookDao(); } 四、在自定义的Application类中声明书籍数据库的唯一实例 为了避免重复打开数据库造成的内存泄漏问题,每个数据库在App运行过程中理应只有一个实例,此时要求开发者自定义新的...Application类,在该类中声明并获取书籍数据库的实例,并将自定义的Application类设为单例模式,保证App运行之时有且仅有一个应用实例。...再打开记录读取页面,从数据库读取书籍信息并展示在页面上,如下图所示。 点此查看Android开发笔记的完整目录
如果数据表不是特别大,这么做是可以的;但是,如果数据表很大或者数据会随着应用的使用而不断增加,就会引起问题。如果这样的问题确实发生了,从长远来讲,这种创建表格方式将不是一个好选择。...介绍 在本文中,我们将会学习如何实现服务器端的分页,搜索和排序功能。从长远来讲,这是一种更好的方式来应对数据集特别大的情况。 我们将会修改前文中的源代码,现在就开始吧!...这是由于绑定将会提供一个附着在控制器上的强类型的模型,这将有助于我们避免读取请求参数,也会将我们从请求的参数类型转换中解救出来。...绑定的好处之一是:如果业务需要,可以在请求中发送一个自定义参数。...你也可以通过 ADO.Net 来实现,唯一需要做的,就是从 DataTableResponse 实例行为中返回 JSON , 如果在脚本中正确定义了行,数据表就会正确的显示数据。
数据访问接口对象 中的 查询方法 , 其返回值类型改为 LiveData 类型 , LiveData 的泛型为 原来的查询方法的返回值类型 ; Dao 查询方法的返回值由 List...数据库访问对象接口 的定义方式需要作出改变 , 涉及到数据库查询的 接口方法时 , 其返回值需要 返回 LiveData 类型 , 泛型设置为 List 类型 ; /**...返回值类型的查询方法 ; /** * 查询数据库表 */ @Query("select * from student") fun query(): LiveData...>> 类型 返回值 ; 手动主动调用的查询 数据库的 方法接口 , 返回 List 类型 返回值 ; /** * 查询数据库表 */ @Query(...Entity 实体 / 同时定义数据库表 和 对鹰的实体类 * 设置该数据类对应数据库中的一张数据表, 表名为 student * 该数据库表中的数据对应一个 Student 类实例对象 */
; return "home"; } } 这个和之前的API的接口有一点不同,首先是没有@ResponseBody注解,然后是方法的返回值是一个String,这个String不是...引入MySQL/MariaDB MySQL被Oracle收走之后,他的father另外创建了新的社区分支MariaDB, 据说用法和MySQL一致。...即实现了每次id都增加1 反引号包裹字段名是为了防止与关键字冲突 INT 是指数字类型,括号里的11是指MySQL里的显示宽度,和最大值取值范围无关,是指需要多少位来表示这个数字,不够长度的补齐。...字段类型要一致。关于Java类型和SQL的数据库表映射规则,请查阅官网。...,不要用* varchar的映射为String int的映射为Integer datetime的映射为time 此处的映射为一个lambda表达式,从结果集中选择想要的字段来创建我们的映射关系 最后一个参数是占位符的值
虽然这看起来很简单,但是由于 SQLite 并没有提供用于此操作的 API,因此我们需要根据 ALERT TABLE 实现,有如下几步操作: 获取需要执行更改的表 创建一个新表,满足更改后的表结构 将旧表的数据插入到新表中...使用全新关系查询功能 为了表示前面所示的音乐人与其歌曲之间的关系,我们现在可以编写一个简单的 DAO 方法,其返回类型为 Map,而我们需要做的仅仅是提供 @Query 和返回标记,Room 将为您处理其余的一切...MapInfo 注解使您可以灵活地使用特定列,而不是整个 data 类从而进行更加自定义的映射。 其他优势 关系查询方法的另一个好处是支持更多的数据操作,可以通过这个新功能来支持分组、筛选等功能。...} 支持原生 Paging 3.0 API Room 现在支持为返回值类型为 androidx.paging.PagingSource 且带 @Query 注解的方法生成实现。...通过依赖 androidx.room:room-rxjava3,您可以声明返回值类型为 Flowable、Single、Maybe 和 Completable 的 DAO 方法。
每个类的成员对应表中的列。列名和类型与类中每个字段的名称和类型一致。如果您希望改变列名而不使用类中的变量名称作为列名,可以通过 @ColumnInfo 注解来修改。...查询数据 为了能够查询表数据,我们这里创建一个抽象函数,并且为其添加 @Query 注解,注解后紧跟 SQL 请求语句: 该语句从单词数据表中请求全部单词,并且以字母顺序排序。...我们希望当数据库中的数据发生改变的时候,能够得到相应的通知,所以我们返回一个 Flow>。由于返回类型是 Flow,Room 会在后台线程中执行数据请求。...如果我们希望 Room 查询不是在 Room 自身创建的 IO Executor 中执行,而是在另外的 Executor 中执行,我们需要通过调用 setQueryExecutor() 将新的 Executor...比如您可以指定 Room 如何处理数据库冲突、可以通过创建 TypeConverters 存储原生 SQLite 无法存储的数据类型 (比如 Date 类型)、可以使用 JOIN 以及其它 SQL 功能实现复杂的查询
的属性代码: Special类: public class Special { private int id; private String name; private String...,返回的集合的元素类型就是这个属性的类型 26 hql = "SELECT e.id,e.name FROM Employee e"; // 查询多个列,返回的集合的元素类型是Object数组 27...34 // List list = query.list(); // 查询的结果是一个List集合 35 // Employee employee = (Employee) query.uniqueResult...Long型的 46 hql = "SELECT min(id) FROM Employee"; // 返回的结果是id属性的类型 47 48 //8,分组: Group By ......>15")// 106 .executeUpdate(); // 返回int型的结果,表示影响了多少行。
中更新 Pager 的构造函数来使用新的 PagingSource 了: fun getSearchResultStream(query: String): Flow>...本地的数据库要如何填充数据呢?来看看 RemoteMediator,当数据库中的数据加载完毕时,它负责从网络加载更多数据。让我们看看它是如何工作的。...更新数据库并通知 Paging,这是我们自己的工作。与 PagingSource 类似,RemoteMediator 有两个泛型参数: 查询参数类型和返回值类型。...第一个方法是 initialize(),它是在所有加载开始前,RemoteMediator 调用的第一个方法,它的返回值为 InitializeAction。...我们可以观察到,该扩展函数的名字中包含了一个类型: LoadState。让我们进一步了解这一类型。
String = "", @Ignore var tempReference: Int = 0 ) : RealmObject() 这里如果你使用 Kotlin 的话,唯一值得注意的是,...用 @Database 注解的类必须包含一个抽象的方法,它含有 0 个参数,并返回一个使用 @Dao 注解的类。...并且,当然随着元素的数量级的增加,差距变得越来越大!对于一个新成员来说,表现得还行。可以说非常好。 ? 查询同样看上去是 ObjectBox 的一个强项。测试中采用了字符串和索引,结果不言自明。...Realm 则装备了最多的令人惊奇的武器,它的这些特性包括自定义配置,加密和更多其他功能(这也是它尺寸比较大的原因之一)。 结论 我们可以看到,不论你选择了哪条路,它都有着自己的长处和短处。...如果你需要速度和效率,很明显 ObjectBox 是一个不错的选择。然而,如果你被应用的大小所限制,被那 64k 个方法所限制,同时你也愿意去使用 SQL 语句,那么 Room 是一个很好的解决方案。
@AndroidEntryPoint:创建一个依赖容器,该容器遵循Android类的生命周期 @Module:告诉Hilt如何提供不同类型的实例 @InstallIn:用来告诉Hilt这个模块会被安装到哪个组件上...,需要对该模块使用Module注解和InstallIn注解绑定到对应Android类的生命周期,显然整个APP运行过程中,我们都要使用网络模块,所以选择绑定Application @InstallIn(...相关基类 使用Room数据库,首先创建Entity,这边加了一个页码的字段: @Entity data class MovieEntity( @PrimaryKey val id: Int..., val title: String, val cover: String, val rate: String, val page: Int//页码 ) 创建Dao,Room...对象为Paging类型的,因为我们MovieDao返回的是一个PagingSourceInt, MovieEntity>对象,所以需要把MovieEntity转换为MovieItemModel