当前位置:网站首页>[Android] Room - Alternative to SQLite
[Android] Room - Alternative to SQLite
2022-07-31 02:45:00 【Bin Youwei】
SQLitehow comeRoom给替代了?
SQLiteWhy is it replaced?
Sqlite
从2000年问世至今,已有20多年历史,在这二十多年里,Sqlite
已由原先的1.0version upgrade current3.0版本,but,even nowAndroid最新支持的2.3.0版本,它在AndroidThere are still a series of shortcomings,如下:
- 没有原始 SQL 查询的编译时验证.
- requires a lot of boilerplate code in SQL 查询和数据对象之间进行转换.
- 虽然这些 API 功能强大,but they are quite low level,Requires a lot of time and effort to use.
针对Sqlite
一系列的问题,realm
(适用于ios、Android)、ObjectBox
(跨端,Claims to be the fastest)、greenDao
etc. local database target,all to replaceSQLite
,甚至到后面,Even the official out of a new database —— Room
,It's going to go completelySqlite
化?
答案是否定的,以上的数据库中,greenDAO
、Room
都是在Sqlite
进行修改、优化.ObjectBox
是由greenDAO
products developed by the development team,他们在greenDAO
的Github首页,向大家推荐ObjectBox
数据库,而greenDAO
For more than a year did not update,也许,是greenDao
The peak has passed,It is difficult to stand on the top again, so they are slowly losing hope for the future(个人猜想).
那为啥,取代SQLite
的是Room
而不是greenDao
呢?个人认为,It's all because of the official“官宣”导致的.在Android Developers官网找到SQLite
's introductory page and user guide,you will find words like this:
we highly recommended using the Room Persistence Library as an abstraction layer for accessing information in your app’s SQLite databases.
我们强烈建议使用 Room Persistence Library as an abstraction layer to access the application's SQLite 数据库中的信息.
放弃SQLite
,persuade us to useRoom
的原因就是SQLite
的缺点与Room
的优点.
Room
优点:
- 简化的数据库迁移路径.
- SQL 查询的编译时验证.
- Handy Notes,Minimize duplication and error-prone boilerplate code.
集成Room
Room 包含三个主要组件,分别是:
- Database:The database class that holds the database and serves as the main access point for the underlying connection to the application's persistent data.
- Entity:A data entity representing a table in the application database.
- Dao:数据访问对象,Provide your application can be used to query the database、更新、Methods of inserting and deleting data.
导入依赖
implementation("androidx.room:room-runtime:2.4.2")
annotationProcessor("androidx.room:room-compiler:2.4.2")
// 使用 Kotlin 注释处理工具 (kapt)
kapt("androidx.room:room-compiler:2.4.2")
注意:Kotlin Plugin support for annotation processors,如 Dagger 或 DBFlow . in order for them to be Kotlin 类一起工作,使用
kapt
需要应用kotlin-kapt
插件.
apply plugin: 'kotlin-kapt'
Click to view the latest version dependencies
RoomThere are three steps to using,分别是Database、Entity、Dao,The data can only be written after the creation is completed、修改等操作.
Entity(数据实体)
在 Room 中,You can define entities to represent the objects you want to store.Each entity corresponds to the associated Room 数据库中的一个表,Each instance of an entity represents a row of data in the corresponding table.
Kotlin 版本的 Entity 与 Java 版本的 Entity 写法不一,Java 版本的 Entity The normal way of writing is to create a new entity class and implement variablesget、set方法,Kotlin 版本的 Entity 使用了data class
关键字,在 Kotlin 中,使用data class
The marked class is a data class,This class will automatically rewrite Kotlin 的超类Any
的equals(other: Any?)
、hashCode()
、toString()
方法,For more details, please go to→Kotlin 数据类(Data)
将data class
声明为 Room 的数据类,需使用@Entity
注解声明,默认情况下,Room 会使用类名作为数据库表名,If you do not want the class name to be the same as the database table name,可在@Entity
注解设置tableName
参数,如:@Entity(tableName = "自定义的数据库表名")
,添加参数后,At this time, the database table name generated by this class will no longer be the class name..
@Entity
data class Classes(
@PrimaryKey val classesId: String,
@ColumnInfo val classesName: String
)
其它注解
Annotation | Describe |
---|---|
@PrimaryKey | 用于唯一标识相应数据库表中的每一行 |
@ColumnInfo | Define the column names of the data table |
@Ignore | Do not add fields to datatables |
@NonNull | The return value of a field or method cannot benull |
@Entity
详细使用方式见:使用 Room 实体定义数据
Dao(数据访问对象)
Dao:Provides methods for the rest of the application to interact with data in the data table.
Dao是一个接口类,Do not need to write the method body,Annotation can be used directly instead,Additions, deletions, and changes correspond to the following four annotations respectively:
Annotation | Describe |
---|---|
@Insert | 增 |
@Delete | 删 |
@Update | 改 |
@Query | 查 |
注解使用方式如下:
@Dao
interface ClassesDao {
/** * Add multiple classes */
@Insert
fun addMultipleClasses(vararg classes: Classes)
/** * 删除某条数据 */
@Delete
fun deleteClasses(classes: Classes)
/** * 修改某条数据 */
@Update
fun updateClasses(classes: Classes)
/** * 查询classes表的数据 */
@Query("select * from classes")
fun getAllClasses() : List<Classes>
}
在 Room 中,Queries with values are represented by colons,如下代码,means looking for className Equal to invoke the interface with the value.
@Query("select * from classes where className = :classesName")
fun getAllClasses(classesName: String) : List<Classes>
Dao详细使用方式见:使用 Room DAO 访问数据
Database(数据库)
Entity、Dao都已经定义了,The last step is to create the database class to hold the data,The created class must meet the three conditions of the database:
- The class must be an extension
RoomDatabase
类的抽象类 . - 对于与数据库关联的每个 Dao 类,The database class must define a class with zero parameters and return Dao abstract method of class instance.
- 该类必须使用
@Database
包含一个entities
Annotation of the array to annotate,This array lists all data entities associated with the database(包括数据库版本).
@Database(entities = [Classes::class/*Entities contained in the database*/], version = 1, exportSchema = false)
abstract class SchoolDatabase : RoomDatabase() {
/** * 调用该方法获取Dao,来调用Classestable interface methods */
abstract fun classDao(): ClassesDao
}
使用
Room.databaseBuilder(applicationContext, SchoolDatabase::class.java, "数据库名称")
.build()
.classDao()
.addClasses(classes)
效果
数据迁移
Why do databases need to migrate data?
Everyone may encounter such a problem in the process of developing a local database,After modifying the fields in the database,Restart will crash.
When some students encounter this problem, they may use such keywords to search:The solution to the flashback of database field modification.The result of the search is that you will be asked to uninstallapp重新安装就好,problem can be solved.但是,This seemingly correct method is actually fatal.
Modify the local database once,打包发布,用户更新appThen if you use a local database,会报Room 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.
的异常错误.
一个appinterface if in8秒内没有加载完成,就会流失70%用户,8second law,How many users will be lost in a flashback??解决上述问题,Only the database can be migrated,And data migration,Divided into automatic migration and manual migration.
自动迁移
Automatic migration provides four annotations for automatic migration,分别是:
- @DeleteTable(Repeatable comments for declaring deleted tables)
- @RenameTable(Repeatable comments for declaring rename tables)
- @DeleteColumn(Repeatable comments for declaring deleted columns)
- @RenameColumn(Repeatable comments for declaring rename columns)
使用方式如下:
// Database class before version update.
@Database(
version = 1,
entities = [User::class]
)
abstract class AppDatabase : RoomDatabase() {
...
}
// Database class after version update.
@Database(
version = 2,
entities = [User::class],
exportSchema = true,
autoMigrations = [
AutoMigration (from = 1, to = 2)
]
)
abstract class AppDatabase : RoomDatabase() {
...
}
Since currently only the above four annotations are officially provided for automatic migration,How to add fields becomes a mystery,If you learned about the newly added data table fields of automatic migration when watching this article,Hope you can share it in the comments.
注意:
1、 使用自动迁移exportSchema
必须设置为true
,Avoid migration failures.
2、Automatic migration is only available for 2.4.0-alpha01 及更高版本,低版本、Scenarios involving complex schema changes must use manual migrations.
参考文章:Room 数据库迁移
手动迁移
The first step of manual database migration,Modify the data table structure first.
@Entity
data class Classes(
@PrimaryKey(autoGenerate = true) val classesId: Int = 0,
@ColumnInfo(name = "className") var classesName: String,
// 新增的列
@ColumnInfo(name = "classesNum") var classesNum: String
)
Manual migration using toRoomDatabase.Builder
的addMigrations(@NonNull Migration... migrations)
方法,将新增的Migration
Classes are put in to complete the migration.
Room 的底层使用的是 SQLite ,The data migration usesSQLite 的 execSQL(String sql)
方法执行 sql 语句对数据库进行修改,to complete the migration,代码如下:
var db: SchoolDatabase ?= null
// 单例模式的双重检查锁
fun getDataBase(context: Context) : SchoolDatabase{
if (db == null){
synchronized(SchoolDatabase::class.java){
if (db == null){
db = Room.databaseBuilder(context.applicationContext, SchoolDatabase::class.java, "school")
// .fallbackToDestructiveMigration()
// 添加数据迁移
.addMigrations(MIGRATION_1_TO_2)
.build()
}
}
}
return db as SchoolDatabase;
}
// MigrationThe two parameters of the instance refer to what version the current version is upgraded to
val MIGRATION_1_TO_2 : Migration = object : Migration(1, 2) {
override fun migrate(database: SupportSQLiteDatabase) {
// Add a new column using 底层SQLite + sql 语法,The same is true for other additions, deletions and modifications
database.execSQL("alter table classesNum add column 新增的列名 列名的数据类型 default 'null'")
}
}
Finally, don't forget to put on the database class name@Database
注解的version
parameter to the latest version,再次 run 即可完成迁移.
结合RxJava使用
Room 执行数据库操作,By default, child threads are used to execute,Callable if it needs to be executed on the main threadRoom.databaseBuilder
的allowMainThreadQueries()
来禁用 Room The main thread query checks,但不建议这样操作,This will increase the trigger ANR 的概率.
如果每次执行 Room Create a new operationThread
并实现Runnable
接口,It's not easier to trigger ANR 吗?
为此,officially launched a Rxjava Libraries used in combination,Easy to switch between threads.
// optional - RxJava3 support for Room
implementation("androidx.room:room-rxjava3:2.4.2")
// RxJava3
implementation ("io.reactivex.rxjava3:rxjava:3.1.3")
implementation ("io.reactivex.rxjava3:rxandroid:3.0.0")
具体结合 RxJava The operation can refer to the article:
1、Room数据库实战:搭配RxJava使用与封装
2、Room配合RxJava2,How to use, experience and precautions
参考文档
1、Android Room 代码示例
2、Android Developers —— Room
3、Android Developers —— Room 使用指南
4、Android Developers —— Defining data using Room entities
边栏推荐
- 图解lower_bound&upper_bound
- 二层广播风暴(产生原因+判断+解决)
- Introduction and use of Drools WorkBench
- Mathematics to solve the problem - circular linked list
- How to do a startup CTO?
- YOLOV5 study notes (2) - environment installation + operation + training
- Unity界面总体介绍
- Number 16, top posts
- Inter-vlan routing + static routing + NAT (PAT + static NAT) comprehensive experiment
- Pythagorean tuple od js
猜你喜欢
To write good test cases, you must first learn test design
Unity界面总体介绍
Layer 2 broadcast storm (cause + judgment + solution)
Coldfusion file read holes (CVE - 2010-2861)
YOLOV5学习笔记(三)——网络模块详解
mycat的主从关系 垂直分库 水平分表 以及mycat分片联表查询的配置详解(mysql5.7系列)
Pythagorean tuple od js
General introduction to the Unity interface
基于opencv实现人脸检测
The whole process scheduling, MySQL and Sqoop
随机推荐
mmdetection训练一个模型相关命令
f.grid_sample
Why is String immutable?
基于opencv实现人脸检测
mysql view
Discourse 自定义头部链接(Custom Header Links)
Teach you how to configure Jenkins automated email notifications
19. Support Vector Machines - Intuitive Understanding of Optimization Objectives and Large Spacing
Brute Force/Adjacency Matrix Breadth First Directed Weighted Graph Undirected Weighted Graph
Mathematical Ideas in AI
怎样做好一个创业公司CTO?
局域网电脑硬件信息收集工具
Layer 2 broadcast storm (cause + judgment + solution)
【C语言基础】解决C语言error: expected ‘;‘, ‘,‘ or ‘)‘ before ‘&‘ token
First acquaintance with C language -- array
String为什么不可变?
How to design the changing system requirements
php 网站的多语言设置(IP地址区分国内国外)
Intranet Infiltration - Privilege Escalation
Introduction to flask series 】 【 flask - using SQLAlchemy