项目中使用了GreenDao创建数据库,建立了一个库并在其中生成了2个表,现在做整体优化,想使用Room创建数据库,毕竟Room是google官方产品,还是值得尝试一波的。
一:对于Room的使用,关注三个点:
1.创建Entity:直接上代码(部分代码省略)
第一个Entity
@Entity(tableName = "login_history_table")
public class LoginHistory {
@PrimaryKey(autoGenerate = true)
Long id;
@ColumnInfo
private String account;
@ColumnInfo
private String pwd;
@ColumnInfo
private String name;
@ColumnInfo
private String quickLoginToken;
@ColumnInfo
private String token;
@ColumnInfo
private String photo;
@ColumnInfo
private int userId;
@ColumnInfo
private long time;
@ColumnInfo
private int loginState = 0;
@ColumnInfo
private int isInvalid = 0;
}
第二个Entity
@Entity(tableName = "stat_event")
data class StatEvent(
@PrimaryKey(autoGenerate = true) val id: Int,
@ColumnInfo(name = "actionCode")
var actionCode: String? = null,
@ColumnInfo(name = "userId")
var userId: Int? = null,
@ColumnInfo(name = "reportTime")
var reportTime: Long? = null,
@ColumnInfo(name = "params1")
var params1: String? = null,
@ColumnInfo(name = "params2")
var params2: String? = null,
) {
}
2.创建对应Dao:
@Dao
interface LoginHistoryDao {
@Insert
fun insert(history: LoginHistory)
@Delete
fun delete(history: LoginHistory)
@Update
fun update(history: LoginHistory)
@Query("select * from login_history_table order by time desc")
fun getAllHistory(): List?
@Query("select * from login_history_table order by time desc limit :count")
fun getHistoryLimit(count: Int): List?
@Query("select * from login_history_table where userId=:id")
fun getHistory(id: Int): LoginHistory?
}
@Dao
interface StatEventDao {
@Insert
fun insert(list: List)
@Insert()
fun insert(event: StatEvent)
@Query("select * from stat_event")
fun getAllEvent(): List?
@Delete
fun deleteAll(events: List?)
}
3.创建数据库db单例类:
@Database(entities = [StatEvent::class,LoginHistory::class], version = 2)
abstract class StatEventDb : RoomDatabase() {
abstract fun statEventDao(): StatEventDao
abstract fun loginHistoryDao(): LoginHistoryDao
companion object {
private var instance: StatEventDb? = null
fun get(context: Context): StatEventDb {
if (instance == null) {
//注释2
instance = Room.databaseBuilder(context, StatEventDb::class.java, "stat_event.db")
.fallbackToDestructiveMigration()
//是否允许在主线程进行查询
.allowMainThreadQueries()
.build()
}
return instance!!
}
}
}
4.使用示例:
StatEventDb.get(BaseApplication.getInstance()).statEventDao().insert(event)
二:升级:
我们做个示例,针对于其中一个表做升级,对
login_history_table 表格增加一个字段,testVersion。
直接上代码:
1.Entity改变:
@Entity(tableName = "login_history_table")
public class LoginHistory {
@PrimaryKey(autoGenerate = true)
Long id;
@ColumnInfo
private String account;//邮箱或者手机号码
@ColumnInfo
private String pwd;
@ColumnInfo
private String name;
@ColumnInfo
private String quickLoginToken;
@ColumnInfo
private String token;
@ColumnInfo
private String photo;
@ColumnInfo
private int userId;
@ColumnInfo
private long time;
//0:未登录,1:已登录,2:正在登陆中
@ColumnInfo
private int loginState = 0;
//0:正常,1:失效
@ColumnInfo
private int isInvalid = 0;
@ColumnInfo
private long testVersion=0;
}
2.DB类的改变:
@Database(entities = [StatEvent::class, LoginHistory::class], version = 3)
abstract class StatEventDb : RoomDatabase() {
abstract fun statEventDao(): StatEventDao
abstract fun luckyCartDao(): LuckyCartDao
abstract fun loginHistoryDao(): LoginHistoryDao
companion object {
private var instance: StatEventDb? = null
fun get(context: Context): StatEventDb {
if (instance == null) {
//注释2
instance = Room.databaseBuilder(context, StatEventDb::class.java, "stat_event.db")
.fallbackToDestructiveMigration()
//添加升级策略
.addMigrations(Migration2_3())
//是否允许在主线程进行查询
.allowMainThreadQueries()
.build()
}
return instance!!
}
}
}
3.Migration2_3类:
class Migration2_3 : Migration(2, 3) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("CREATE TABLE temp_Stat_event (" +
"id INTEGER PRIMARY KEY NOT NULL," +
"actionCode TEXT," +
"userId INTEGER," +
"reportTime INTEGER," +
"params1 TEXT," +
"params2 TEXT)");
database.execSQL("INSERT INTO temp_Stat_event (id, actionCode, userId,reportTime,params1,params2) " +
"SELECT id, actionCode, userId,reportTime,params1,params2 FROM stat_event");
database.execSQL("DROP TABLE stat_event");
database.execSQL("ALTER TABLE temp_Stat_event RENAME TO stat_event");
database.execSQL("CREATE TABLE temp_login_history_table (" +
"id INTEGER PRIMARY KEY," +
"account TEXT," +
"pwd TEXT," +
"name TEXT," +
"quickLoginToken TEXT," +
"token TEXT," +
"photo TEXT," +
"userId INTEGER," +
"time INTEGER," +
"loginState INTEGER NOT NULL DEFAULT null," +
"isInvalid INTEGER NOT NULL DEFAULT null)" )
database.execSQL("INSERT INTO temp_login_history_table (id, account, pwd,name,quickLoginToken,token,photo,userId,time,loginState,isInvalid) " +
"SELECT id, account, pwd,name,quickLoginToken,token,photo,userId,time,loginState,isInvalid FROM login_history_table");
database.execSQL("DROP TABLE login_history_table");
database.execSQL("CREATE TABLE login_history_table (" +
"id INTEGER PRIMARY KEY," +
"account TEXT," +
"pwd TEXT," +
"name TEXT," +
"quickLoginToken TEXT," +
"token TEXT," +
"photo TEXT," +
"userId INTEGER NOT NULL," +
"time INTEGER NOT NULL," +
"loginState INTEGER NOT NULL DEFAULT null," +
"isInvalid INTEGER NOT NULL DEFAULT null,"+
"testVersion INTEGER NOT NULL )")
database.execSQL("INSERT INTO login_history_table (id, account, pwd,name,quickLoginToken,token,photo,userId,time,loginState,isInvalid,testVersion) " +
"SELECT id, account, pwd,name,quickLoginToken,token,photo,userId,time,loginState,isInvalid ,0 FROM temp_login_history_table");
database.execSQL("DROP TABLE temp_login_history_table");
}
}
对于Migration2_3说明:
对于版本2升级到版本3时,重新创建需要改变的表,创建新的字段,并把旧数据保存进去。对于不改变的表不用执行sql语句,所以上述的stat_event表可以不用执行sql。 上述的sql语句也有部分可以优化。
遇到的报错日志:
对于上述报错,仔细看下错误信息会发现,上面是Expected期望的数据类型,下面是Found执行发现的数据类型,对比会发现不太一样,直接按照Expected的去更改就行。
以上是Room使用的一波体验,希望能给大家有所帮助。
————————————————
版权声明:本文为CSDN博主「卖火柴的大兄弟」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_42789174/article/details/123236639