<link rel="stylesheet" href="https://csdnimg.cn/release/blogv2/dist/mdeditor/css/editerView/kdoc_html_views-1a98987dfd.css">
<link rel="stylesheet" href="https://csdnimg.cn/release/blogv2/dist/mdeditor/css/editerView/ck_htmledit_views-25cebea3f9.css">
<div id="content_views" class="markdown_views prism-tomorrow-night-eighties">
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path>
</svg>
<p></p>
文章目录
一、销毁 和 重建策略
在 Android 中使用 Room 操作 SQLite 数据库 , 如果 SQLite 数据库表 修改比较繁琐 ,
如 : 涉及到 修改 数据库表字段的数据类型 , 需要逐个修改数据库值 ;
该环境下 使用 销毁 和 重建策略 是 最佳的方案 ;
销毁 和 重建策略 执行步骤 : 以 Table 表为例 , 要对 Table 表中的数据进行繁琐的操作 ;
- 首先 , 创建一张 符合 新数据库表结构 的 临时数据库表 Temp_Table 表 ;
- 然后 , 将 旧数据库表 Table 表中的数据 拷贝到 临时数据库表 Temp_Table 表中 , 如果需要修改 , 也在该步骤中进行修改 ;
- 再后 , 删除旧的数据库表 Table 表 ;
- 最后 , 将 临时数据库表 Temp_Table 表 重命名为 Table 表 ;
二、销毁 和 重建策略 核心要点
1、创建 Migration 迁移类 - 重点
在本篇博客中 , 在之前的博客
- 【Jetpack】Room + ViewModel + LiveData 综合使用 ( 核心要点说明 | 组合方式 | 代码示例 )
- 【Jetpack】使用 Room 中的 Migration 升级数据库 ( 修改 Entity 实体类 - 更改数据模型 | 创建 Migration 迁移类 | 修改数据库版本 | 代码示例 )
基础上 , 升级数据库版本 4 ;
数据库 版本 2 和 3 分别在 数据库 版本 1 的基础上新增了一个字段 ;
这里要升级的数据库版本 4 , 要 在 数据库版本 3 的基础上 , 将 integer 类型的字段 sex 的 数据类型 修改为 text 类型 ,
这就需要将 整个数据库表中的数据的 指定字段 需要重新赋值 ;
这就需要 使用 销毁重建 策略 ;
销毁 和 重建策略 执行步骤 :
- 首先 , 创建一张 符合 新数据库表结构 的 临时数据库表;
// 创新临时数据库
database.execSQL(
"CREATE TABLE temp_student (" +
"id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL," +
"name TEXT," +
"age INTEGER NOT NULL," +
"sex TEXT DEFAULT 'M'," +
"degree INTEGER NOT NULL DEFAULT 1)"
)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 然后 , 将 旧数据库表 中的数据 拷贝到 临时数据库表 中 , 如果需要修改 , 也在该步骤中进行修改 ;
// 拷贝数据
database.execSQL(
"INSERT INTO temp_student (name,age,degree)" +
"SELECT name,age,degree FROM student"
)
- 1
- 2
- 3
- 4
- 5
- 再后 , 删除旧的数据库表 ;
// 删除原始表
database.execSQL("DROP TABLE student")
- 1
- 2
- 最后 , 将 临时数据库表 重命名为 原来的表名 ;
// 将临时表命令为原表表明
database.execSQL("ALTER TABLE temp_student RENAME TO student")
- 1
- 2
上述的 四个步骤 , 都在 Migration 的 public void migrate(@NonNull SupportSQLiteDatabase database) 函数中完成 , 每个步骤分别对应一个 SQL 语句 ;
最终定义的 Migration 为 :
/** * 数据库版本 3 升级到 版本 4 的迁移类实例对象 * 销毁重建策略 */ val MIGRATION_3_4: Migration = object : Migration(3, 4) { override fun migrate(database: SupportSQLiteDatabase) { // 创新临时数据库 database.execSQL( "CREATE TABLE temp_student (" + "id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL," + "name TEXT," + "age INTEGER NOT NULL," + "sex TEXT DEFAULT 'M'," + "degree INTEGER NOT NULL DEFAULT 1)" )
<span class="token comment">// 拷贝数据</span> database<span class="token punctuation">.</span><span class="token function">execSQL</span><span class="token punctuation">(</span> <span class="token string-literal singleline"><span class="token string">"INSERT INTO temp_student (name,age,degree)"</span></span> <span class="token operator">+</span> <span class="token string-literal singleline"><span class="token string">"SELECT name,age,degree FROM student"</span></span> <span class="token punctuation">)</span> <span class="token comment">// 删除原始表</span> database<span class="token punctuation">.</span><span class="token function">execSQL</span><span class="token punctuation">(</span><span class="token string-literal singleline"><span class="token string">"DROP TABLE student"</span></span><span class="token punctuation">)</span> <span class="token comment">// 将临时表命令为原表表明</span> database<span class="token punctuation">.</span><span class="token function">execSQL</span><span class="token punctuation">(</span><span class="token string-literal singleline"><span class="token string">"ALTER TABLE temp_student RENAME TO student"</span></span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
2、配置 Migration 迁移类
在 创建 RoomDatabase.Builder 时 , 调用 RoomDatabase.Builder#addMigrations , 设置上述创建的 销毁重建策略的 Migration 迁移类 ;
fun inst(context: Context): StudentDatabase {
if (!::instance.isInitialized) {
synchronized(StudentDatabase::class) {
// 创建数据库
instance = Room.databaseBuilder(
context.applicationContext,
StudentDatabase::class.java,
"student_database.db")
.addMigrations(MIGRATION_1_2)
.addMigrations(MIGRATION_2_3)
.addMigrations(MIGRATION_3_4)
.fallbackToDestructiveMigration()
.allowMainThreadQueries() // Room 原则上不允许在主线程操作数据库
// 如果要在主线程操作数据库需要调用该函数
.build()
}
}
return instance;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
3、修改数据库版本号
在 RoomDatabase 类的 @Database 注解上的 version 数据库版本号参数设置为 4 ;
@Database(entities = [Student::class], version = 4, exportSchema = true)
abstract class StudentDatabase: RoomDatabase() {
- 1
- 2
4、修改实体类数据类型
将 Entity 实体类 Student 类中的 sex 字段 由
/**
* 性别字段
* 数据库表中的列名为 sex
* 数据库表中的类型为 INTEGER 文本类型
*/
@ColumnInfo(name = "sex", typeAffinity = ColumnInfo.INTEGER)
var sex: Int = 0
- 1
- 2
- 3
- 4
- 5
- 6
- 7
修改为 :
/**
* 性别字段
* 数据库表中的列名为 sex
* 数据库表中的类型为 TEXT 文本类型
*/
@ColumnInfo(name = "sex", typeAffinity = ColumnInfo.TEXT)
var sex: String = "M"
- 1
- 2
- 3
- 4
- 5
- 6
- 7
三、完整代码示例
代码地址 : https://github.com/han1202012/Room_ViewModel_LiveData
1、数据库版本 3 代码示例
RoomDatabase 数据库类完整代码
package kim.hsl.rvl
import android.content.Context
import android.util.Log
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
@Database(entities = [Student::class], version = 3, exportSchema = true)
abstract class StudentDatabase: RoomDatabase() {
/**
* 获取 数据库访问 对象
* 这是必须要实现的函数
*/
abstract fun studentDao(): StudentDao
<span class="token keyword">companion</span> <span class="token keyword">object</span> <span class="token punctuation">{<!-- --></span>
<span class="token keyword">lateinit</span> <span class="token keyword">var</span> instance<span class="token operator">:</span> StudentDatabase
<span class="token comment">/**
* 数据库版本 1 升级到 版本 2 的迁移类实例对象
*/</span>
<span class="token keyword">val</span> MIGRATION_1_2<span class="token operator">:</span> Migration <span class="token operator">=</span> <span class="token keyword">object</span> <span class="token operator">:</span> <span class="token function">Migration</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
<span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token function">migrate</span><span class="token punctuation">(</span>database<span class="token operator">:</span> SupportSQLiteDatabase<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
Log<span class="token punctuation">.</span><span class="token function">i</span><span class="token punctuation">(</span><span class="token string-literal singleline"><span class="token string">"Room_StudentDatabase"</span></span><span class="token punctuation">,</span> <span class="token string-literal singleline"><span class="token string">"数据库版本 1 升级到 版本 2"</span></span><span class="token punctuation">)</span>
database<span class="token punctuation">.</span><span class="token function">execSQL</span><span class="token punctuation">(</span><span class="token string-literal singleline"><span class="token string">"alter table student add column sex integer not null default 1"</span></span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token comment">/**
* 数据库版本 2 升级到 版本 3 的迁移类实例对象
*/</span>
<span class="token keyword">val</span> MIGRATION_2_3<span class="token operator">:</span> Migration <span class="token operator">=</span> <span class="token keyword">object</span> <span class="token operator">:</span> <span class="token function">Migration</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
<span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token function">migrate</span><span class="token punctuation">(</span>database<span class="token operator">:</span> SupportSQLiteDatabase<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
Log<span class="token punctuation">.</span><span class="token function">i</span><span class="token punctuation">(</span><span class="token string-literal singleline"><span class="token string">"Room_StudentDatabase"</span></span><span class="token punctuation">,</span> <span class="token string-literal singleline"><span class="token string">"数据库版本 2 升级到 版本 3"</span></span><span class="token punctuation">)</span>
database<span class="token punctuation">.</span><span class="token function">execSQL</span><span class="token punctuation">(</span><span class="token string-literal singleline"><span class="token string">"alter table student add column degree integer not null default 1"</span></span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">fun</span> <span class="token function">inst</span><span class="token punctuation">(</span>context<span class="token operator">:</span> Context<span class="token punctuation">)</span><span class="token operator">:</span> StudentDatabase <span class="token punctuation">{<!-- --></span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token operator">::</span>instance<span class="token punctuation">.</span>isInitialized<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
<span class="token function">synchronized</span><span class="token punctuation">(</span>StudentDatabase<span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
<span class="token comment">// 创建数据库</span>
instance <span class="token operator">=</span> Room<span class="token punctuation">.</span><span class="token function">databaseBuilder</span><span class="token punctuation">(</span>
context<span class="token punctuation">.</span>applicationContext<span class="token punctuation">,</span>
StudentDatabase<span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">.</span>java<span class="token punctuation">,</span>
<span class="token string-literal singleline"><span class="token string">"student_database.db"</span></span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">addMigrations</span><span class="token punctuation">(</span>MIGRATION_1_2<span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">addMigrations</span><span class="token punctuation">(</span>MIGRATION_2_3<span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">fallbackToDestructiveMigration</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">allowMainThreadQueries</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// Room 原则上不允许在主线程操作数据库</span>
<span class="token comment">// 如果要在主线程操作数据库需要调用该函数</span>
<span class="token punctuation">.</span><span class="token function">build</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> instance<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
Student 实体类完整代码
package kim.hsl.rvl
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.Ignore
import androidx.room.PrimaryKey
/**
-
定义数据库表 Entity 实体 / 同时定义数据库表 和 对鹰的实体类
-
设置该数据类对应数据库中的一张数据表, 表名为 student
-
该数据库表中的数据对应一个 Student 类实例对象
/
@Entity(tableName = “student”)
class Student {
/*- @PrimaryKey 设置主键 autoGenerate 为自增
- @ColumnInfo name 设置列名称 / typeAffinity 设置列类型
*/
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = “id”, typeAffinity = ColumnInfo.INTEGER)
var id: Int = 0
/**
- 姓名字段
- 数据库表中的列名为 name
- 数据库表中的类型为 TEXT 文本类型
*/
@ColumnInfo(name = “name”, typeAffinity = ColumnInfo.TEXT)
lateinit var name: String
/**
- 年龄字段
- 数据库表中的列名为 age
- 数据库表中的类型为 INTEGER 文本类型
*/
@ColumnInfo(name = “age”, typeAffinity = ColumnInfo.INTEGER)
var age: Int = 0
/**
- 性别字段
- 数据库表中的列名为 sex
- 数据库表中的类型为 INTEGER 文本类型
*/
@ColumnInfo(name = “sex”, typeAffinity = ColumnInfo.INTEGER)
var sex: Int = 0
/**
- degree字段
- 数据库表中的列名为 sex
- 数据库表中的类型为 INTEGER 文本类型
*/
@ColumnInfo(name = “degree”, typeAffinity = ColumnInfo.INTEGER)
var degree: Int = 0
/**
- 有些属性用于做业务逻辑
- 不需要插入到数据库中
- 使用 @Ignore 注解修饰该属性字段
*/
@Ignore
lateinit var studentInfo: String
/**
- 默认的构造方法给 Room 框架使用
*/
constructor(id: Int, name: String, age: Int) {
this.id = id
this.name = name
this.age = age
}
/**
- 使用 @Ignore 标签标注后
- Room 就不会使用该构造方法了
- 这个构造方法是给开发者使用的
*/
@Ignore
constructor(name: String, age: Int) {
this.name = name
this.age = age
}
/**
- 使用 @Ignore 标签标注后
- Room 就不会使用该构造方法了
- 这个构造方法是给开发者使用的
*/
@Ignore
constructor(id: Int) {
this.id = id
}
override fun toString(): String {
return “Student(id= < / s p a n > < s p a n c l a s s = " t o k e n e x p r e s s i o n " > i d < / s p a n > < / s p a n > < s p a n c l a s s = " t o k e n s t r i n g " > , n a m e = ′ < / s p a n > < s p a n c l a s s = " t o k e n i n t e r p o l a t i o n " > < s p a n c l a s s = " t o k e n i n t e r p o l a t i o n − p u n c t u a t i o n p u n c t u a t i o n " > </span><span class="token expression">id</span></span><span class="token string">, name='</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation"> </span><spanclass="tokenexpression">id</span></span><spanclass="tokenstring">,name=′</span><spanclass="tokeninterpolation"><spanclass="tokeninterpolation−punctuationpunctuation">name', age=$age)”
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
执行结果
先执行数据库版本为 3 的应用 , 输出结果如下 :
2023-06-05 19:17:12.251 I/Room_MainActivity: Observer#onChanged 回调, List<Student>: []
2023-06-05 19:17:12.532 I/Room_MainActivity: 插入数据 S1 : Student(id=0, name='Tom', age=18)
2023-06-05 19:17:12.536 I/Room_MainActivity: Observer#onChanged 回调, List<Student>: [Student(id=1, name='Tom', age=18)]
2023-06-05 19:17:13.036 I/Room_MainActivity: 插入数据 S2 : Student(id=0, name='Jerry', age=16)
2023-06-05 19:17:13.038 I/Room_MainActivity: Observer#onChanged 回调, List<Student>: [Student(id=1, name='Tom', age=18), Student(id=2, name='Jerry', age=16)]
2023-06-05 19:17:13.538 I/Room_MainActivity: 更新数据 S2 : Student(id=2, name='Jack', age=60)
2023-06-05 19:17:13.540 I/Room_MainActivity: Observer#onChanged 回调, List<Student>: [Student(id=1, name='Tom', age=18), Student(id=2, name='Jack', age=60)]
2023-06-05 19:17:14.051 I/Room_MainActivity: 删除数据 id = 1
2023-06-05 19:17:14.060 I/Room_MainActivity: Observer#onChanged 回调, List<Student>: [Student(id=2, name='Jack', age=60)]
2023-06-05 19:17:14.553 I/Room_MainActivity: 主动查询 : LiveData : androidx.room.RoomTrackingLiveData@8726677 , 实际数据 : null
2023-06-05 19:17:14.554 I/Room_MainActivity: 主动查询2 : [Student(id=2, name='Jack', age=60)]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
2、数据库版本 4 代码示例
将数据库版本修改为 4 , 然后执行上述 销毁重建策略 修改 ;
主要是创建了 数据库版本 3 升级到 版本 4 的迁移类实例对象 , 该 Migration 类
RoomDatabase 数据库类完整代码
package kim.hsl.rvl
import android.content.Context
import android.util.Log
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
@Database(entities = [Student::class], version = 4, exportSchema = true)
abstract class StudentDatabase: RoomDatabase() {
/**
* 获取 数据库访问 对象
* 这是必须要实现的函数
*/
abstract fun studentDao(): StudentDao
<span class="token keyword">companion</span> <span class="token keyword">object</span> <span class="token punctuation">{<!-- --></span>
<span class="token keyword">lateinit</span> <span class="token keyword">var</span> instance<span class="token operator">:</span> StudentDatabase
<span class="token comment">/**
* 数据库版本 1 升级到 版本 2 的迁移类实例对象
*/</span>
<span class="token keyword">val</span> MIGRATION_1_2<span class="token operator">:</span> Migration <span class="token operator">=</span> <span class="token keyword">object</span> <span class="token operator">:</span> <span class="token function">Migration</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
<span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token function">migrate</span><span class="token punctuation">(</span>database<span class="token operator">:</span> SupportSQLiteDatabase<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
Log<span class="token punctuation">.</span><span class="token function">i</span><span class="token punctuation">(</span><span class="token string-literal singleline"><span class="token string">"Room_StudentDatabase"</span></span><span class="token punctuation">,</span> <span class="token string-literal singleline"><span class="token string">"数据库版本 1 升级到 版本 2"</span></span><span class="token punctuation">)</span>
database<span class="token punctuation">.</span><span class="token function">execSQL</span><span class="token punctuation">(</span><span class="token string-literal singleline"><span class="token string">"alter table student add column sex integer not null default 1"</span></span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token comment">/**
* 数据库版本 2 升级到 版本 3 的迁移类实例对象
*/</span>
<span class="token keyword">val</span> MIGRATION_2_3<span class="token operator">:</span> Migration <span class="token operator">=</span> <span class="token keyword">object</span> <span class="token operator">:</span> <span class="token function">Migration</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
<span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token function">migrate</span><span class="token punctuation">(</span>database<span class="token operator">:</span> SupportSQLiteDatabase<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
Log<span class="token punctuation">.</span><span class="token function">i</span><span class="token punctuation">(</span><span class="token string-literal singleline"><span class="token string">"Room_StudentDatabase"</span></span><span class="token punctuation">,</span> <span class="token string-literal singleline"><span class="token string">"数据库版本 2 升级到 版本 3"</span></span><span class="token punctuation">)</span>
database<span class="token punctuation">.</span><span class="token function">execSQL</span><span class="token punctuation">(</span><span class="token string-literal singleline"><span class="token string">"alter table student add column degree integer not null default 1"</span></span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token comment">/**
* 数据库版本 3 升级到 版本 4 的迁移类实例对象
* 销毁重建策略
*/</span>
<span class="token keyword">val</span> MIGRATION_3_4<span class="token operator">:</span> Migration <span class="token operator">=</span> <span class="token keyword">object</span> <span class="token operator">:</span> <span class="token function">Migration</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
<span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token function">migrate</span><span class="token punctuation">(</span>database<span class="token operator">:</span> SupportSQLiteDatabase<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
Log<span class="token punctuation">.</span><span class="token function">i</span><span class="token punctuation">(</span><span class="token string-literal singleline"><span class="token string">"Room_StudentDatabase"</span></span><span class="token punctuation">,</span> <span class="token string-literal singleline"><span class="token string">"数据库版本 3 升级到 版本 4"</span></span><span class="token punctuation">)</span>
<span class="token comment">// 创新临时数据库</span>
database<span class="token punctuation">.</span><span class="token function">execSQL</span><span class="token punctuation">(</span>
<span class="token string-literal singleline"><span class="token string">"CREATE TABLE temp_student ("</span></span> <span class="token operator">+</span>
<span class="token string-literal singleline"><span class="token string">"id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,"</span></span> <span class="token operator">+</span>
<span class="token string-literal singleline"><span class="token string">"name TEXT,"</span></span> <span class="token operator">+</span>
<span class="token string-literal singleline"><span class="token string">"age INTEGER NOT NULL,"</span></span> <span class="token operator">+</span>
<span class="token string-literal singleline"><span class="token string">"sex TEXT NOT NULL DEFAULT 'M',"</span></span> <span class="token operator">+</span>
<span class="token string-literal singleline"><span class="token string">"degree INTEGER NOT NULL DEFAULT 1)"</span></span>
<span class="token punctuation">)</span>
<span class="token comment">// 拷贝数据</span>
database<span class="token punctuation">.</span><span class="token function">execSQL</span><span class="token punctuation">(</span>
<span class="token string-literal singleline"><span class="token string">"INSERT INTO temp_student (name, age, degree)"</span></span> <span class="token operator">+</span>
<span class="token string-literal singleline"><span class="token string">"SELECT name, age, degree FROM student"</span></span>
<span class="token punctuation">)</span>
<span class="token comment">// 删除原始表</span>
database<span class="token punctuation">.</span><span class="token function">execSQL</span><span class="token punctuation">(</span><span class="token string-literal singleline"><span class="token string">"DROP TABLE student"</span></span><span class="token punctuation">)</span>
<span class="token comment">// 将临时表命令为原表表明</span>
database<span class="token punctuation">.</span><span class="token function">execSQL</span><span class="token punctuation">(</span><span class="token string-literal singleline"><span class="token string">"ALTER TABLE temp_student RENAME TO student"</span></span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">fun</span> <span class="token function">inst</span><span class="token punctuation">(</span>context<span class="token operator">:</span> Context<span class="token punctuation">)</span><span class="token operator">:</span> StudentDatabase <span class="token punctuation">{<!-- --></span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token operator">::</span>instance<span class="token punctuation">.</span>isInitialized<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
<span class="token function">synchronized</span><span class="token punctuation">(</span>StudentDatabase<span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
<span class="token comment">// 创建数据库</span>
instance <span class="token operator">=</span> Room<span class="token punctuation">.</span><span class="token function">databaseBuilder</span><span class="token punctuation">(</span>
context<span class="token punctuation">.</span>applicationContext<span class="token punctuation">,</span>
StudentDatabase<span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">.</span>java<span class="token punctuation">,</span>
<span class="token string-literal singleline"><span class="token string">"student_database.db"</span></span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">addMigrations</span><span class="token punctuation">(</span>MIGRATION_1_2<span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">addMigrations</span><span class="token punctuation">(</span>MIGRATION_2_3<span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">addMigrations</span><span class="token punctuation">(</span>MIGRATION_3_4<span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">fallbackToDestructiveMigration</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">allowMainThreadQueries</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// Room 原则上不允许在主线程操作数据库</span>
<span class="token comment">// 如果要在主线程操作数据库需要调用该函数</span>
<span class="token punctuation">.</span><span class="token function">build</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> instance<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
Student 实体类代码示例
package kim.hsl.rvl
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.Ignore
import androidx.room.PrimaryKey
/**
-
定义数据库表 Entity 实体 / 同时定义数据库表 和 对鹰的实体类
-
设置该数据类对应数据库中的一张数据表, 表名为 student
-
该数据库表中的数据对应一个 Student 类实例对象
/
@Entity(tableName = “student”)
class Student {
/*- @PrimaryKey 设置主键 autoGenerate 为自增
- @ColumnInfo name 设置列名称 / typeAffinity 设置列类型
*/
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = “id”, typeAffinity = ColumnInfo.INTEGER)
var id: Int = 0
/**
- 姓名字段
- 数据库表中的列名为 name
- 数据库表中的类型为 TEXT 文本类型
*/
@ColumnInfo(name = “name”, typeAffinity = ColumnInfo.TEXT)
lateinit var name: String
/**
- 年龄字段
- 数据库表中的列名为 age
- 数据库表中的类型为 INTEGER 文本类型
*/
@ColumnInfo(name = “age”, typeAffinity = ColumnInfo.INTEGER)
var age: Int = 0
/**
- 性别字段
- 数据库表中的列名为 sex
- 数据库表中的类型为 TEXT 文本类型
*/
@ColumnInfo(name = “sex”, typeAffinity = ColumnInfo.TEXT)
var sex: String = “M”
/**
- 性别字段
- 数据库表中的列名为 sex
- 数据库表中的类型为 INTEGER 文本类型
/
/@ColumnInfo(name = “sex”, typeAffinity = ColumnInfo.INTEGER)
var sex: Int = 0*/
/**
- degree字段
- 数据库表中的列名为 sex
- 数据库表中的类型为 INTEGER 文本类型
*/
@ColumnInfo(name = “degree”, typeAffinity = ColumnInfo.INTEGER)
var degree: Int = 0
/**
- 有些属性用于做业务逻辑
- 不需要插入到数据库中
- 使用 @Ignore 注解修饰该属性字段
*/
@Ignore
lateinit var studentInfo: String
/**
- 默认的构造方法给 Room 框架使用
*/
constructor(id: Int, name: String, age: Int) {
this.id = id
this.name = name
this.age = age
}
/**
- 使用 @Ignore 标签标注后
- Room 就不会使用该构造方法了
- 这个构造方法是给开发者使用的
*/
@Ignore
constructor(name: String, age: Int) {
this.name = name
this.age = age
}
/**
- 使用 @Ignore 标签标注后
- Room 就不会使用该构造方法了
- 这个构造方法是给开发者使用的
*/
@Ignore
constructor(id: Int) {
this.id = id
}
override fun toString(): String {
return “Student(id= < / s p a n > < s p a n c l a s s = " t o k e n e x p r e s s i o n " > i d < / s p a n > < / s p a n > < s p a n c l a s s = " t o k e n s t r i n g " > , n a m e = ′ < / s p a n > < s p a n c l a s s = " t o k e n i n t e r p o l a t i o n " > < s p a n c l a s s = " t o k e n i n t e r p o l a t i o n − p u n c t u a t i o n p u n c t u a t i o n " > </span><span class="token expression">id</span></span><span class="token string">, name='</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation"> </span><spanclass="tokenexpression">id</span></span><spanclass="tokenstring">,name=′</span><spanclass="tokeninterpolation"><spanclass="tokeninterpolation−punctuationpunctuation">name', age=$age)”
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
执行结果
执行结果如下 :
2023-06-05 19:18:58.864 I/Room_StudentDatabase: 数据库版本 3 升级到 版本 4
2023-06-05 19:18:58.909 I/Room_MainActivity: Observer#onChanged 回调, List<Student>: [Student(id=1, name='Jack', age=60)]
2023-06-05 19:18:59.346 I/Room_MainActivity: 插入数据 S1 : Student(id=0, name='Tom', age=18)
2023-06-05 19:18:59.351 I/Room_MainActivity: Observer#onChanged 回调, List<Student>: [Student(id=1, name='Jack', age=60), Student(id=2, name='Tom', age=18)]
2023-06-05 19:18:59.853 I/Room_MainActivity: 插入数据 S2 : Student(id=0, name='Jerry', age=16)
2023-06-05 19:18:59.855 I/Room_MainActivity: Observer#onChanged 回调, List<Student>: [Student(id=1, name='Jack', age=60), Student(id=2, name='Tom', age=18), Student(id=3, name='Jerry', age=16)]
2023-06-05 19:19:00.362 I/Room_MainActivity: 更新数据 S2 : Student(id=2, name='Jack', age=60)
2023-06-05 19:19:00.371 I/Room_MainActivity: Observer#onChanged 回调, List<Student>: [Student(id=1, name='Jack', age=60), Student(id=2, name='Jack', age=60), Student(id=3, name='Jerry', age=16)]
2023-06-05 19:19:00.875 I/Room_MainActivity: 删除数据 id = 1
2023-06-05 19:19:00.877 I/Room_MainActivity: Observer#onChanged 回调, List<Student>: [Student(id=2, name='Jack', age=60), Student(id=3, name='Jerry', age=16)]
2023-06-05 19:19:01.377 I/Room_MainActivity: 主动查询 : LiveData : androidx.room.RoomTrackingLiveData@b957950 , 实际数据 : null
2023-06-05 19:19:01.378 I/Room_MainActivity: 主动查询2 : [Student(id=2, name='Jack', age=60), Student(id=3, name='Jerry', age=16)]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12