dependencies {
def room_version = "2.4.1"
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"
implementation "androidx.room:room-rxjava2:$room_version"
implementation "androidx.room:room-rxjava3:$room_version"
implementation "androidx.room:room-guava:$room_version"
testImplementation "androidx.room:room-testing:$room_version"
implementation "androidx.room:room-paging:2.4.1"
}
@Entity(tableName = "student")
public class Student {
@NonNull
@PrimaryKey(autoGenerate = true)
private int id;
@ColumnInfo(name = "firstName")
private String name;
@Embedded
private Grade grade;
public Student() {
}
@Ignore
public Student(int id, String name, Grade grade) {
this.id = id;
this.name = name;
this.grade = grade;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Grade getGrade() {
return grade;
}
public void setGrade(Grade grade) {
this.grade = grade;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", grade=" + grade.toString() +
'}';
}
}
上表中的嵌套类:
public class Grade {
private int math;
private int english;
private int chinese;
@Ignore
private int history;
public Grade() {
}
@Ignore
public Grade(int math, int english, int chinese, int history) {
this.math = math;
this.english = english;
this.chinese = chinese;
this.history = history;
}
public int getHistory() {
return history;
}
public void setHistory(int history) {
this.history = history;
}
public int getMath() {
return math;
}
public void setMath(int math) {
this.math = math;
}
public int getEnglish() {
return english;
}
public void setEnglish(int english) {
this.english = english;
}
public int getChinese() {
return chinese;
}
public void setChinese(int chinese) {
this.chinese = chinese;
}
@Override
public String toString() {
return "Grade{" +
"math=" + math +
", english=" + english +
", chinese=" + chinese +
", history=" + history +
'}';
}
}
@Dao
public interface StudentDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
List<Long> insert(Student... students);
@Insert(onConflict = OnConflictStrategy.REPLACE)
Long insert(Student student);
@Insert(onConflict = OnConflictStrategy.REPLACE)
List<Long> insert(List<Student> list);
@Update
int update(Student student);
@Update
int update(Student... student);
@Query("select * from student where firstName =:name")
List<Student> getByName(String name);
@Query("SELECT * FROM student where id = :id")
Student getById(int id);
@Query("select * from student")
List<Student> loadAll();
@Query("select * from student")
Flowable<List<Student>> getAll();
@Delete
int deleteById(Student student);
@Query("delete from student")
int deleteAll();
@Query("delete from student where firstName = :name")
int deleteByName(String name);
}
Room中升级可以根据情景不同分为两种方式:
在创建Database对应类时设置fallbackToDestructiveMigration(),这样每次要升级时直接更改数据库版本号就可以了,不需要其它额外的操作,不过这样用户体验不大好。
sInstance = Room.databaseBuilder(context,AppDatabase.class,"data")
.fallbackToDestructiveMigration()
.build();
Room中提供了专门用于升级的Migration类,通过它可以优雅的实现数据库升级,原来的数据不会丢失。
首先在自己的数据类中添加字段:
如我想在student表中增添sport字段,则首先在对应类中添加字段:( 此字段只要在student表中即可,也可添加至嵌套类,如将sport添加至grade中)
@Entity(tableName = "student")
public class Student {
@NonNull
@PrimaryKey(autoGenerate = true)
private int id;
@ColumnInfo(name = "firstName")
private String name;
@ColumnInfo(name = "sport")
private Integer sport;
@Embedded
private Grade grade;
public Student() {
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", sport=" + sport +
", grade=" + grade.toString() +
'}';
}
@Ignore
public Student(int id, String name, Grade grade) {
this.id = id;
this.name = name;
this.grade = grade;
}
public Integer getSport() {
return sport;
}
public void setSport(Integer sport) {
this.sport = sport;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Grade getGrade() {
return grade;
}
public void setGrade(Grade grade) {
this.grade = grade;
}
}
然后在表中创建字段:
sInstance = Room.databaseBuilder(context,AppDatabase.class,"data")
.addMigrations(MIGRATION_1_2)
.build();
static final Migration MIGRATION_1_2 = new Migration(1,2) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
database.execSQL("ALTER TABLE student ADD COLUMN sport INTEGER");
}
};
然后需要将数据库版本修改至2,如下:
@Database(entities = {Student.class}, version = 2, exportSchema = true)
public abstract class AppDatabase extends RoomDatabase {
}
至此数据库升级完成,对比数据:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RQ6pkDtf-1644985406952)(C:\Users\过客\AppData\Roaming\Typora\typora-user-images\image-20220216114331762.png)]
由于此前没有sport字段,所以对于之前存储的数据sport字段为默认值,此后就为存储的数值了。
注意:
若你新添加的字段上添加有@NoNull注解,如:
@NonNull
@ColumnInfo(name = "sport")
private Integer sport;
那么在创建时也要与之对应:
database.execSQL("ALTER TABLE student ADD COLUMN sport INTEGER NOT NULL DEFAULT 1");
上面两者需要对应,否则会抛异常。
上面的升级方式都是渐进式的一级一级往上升,但实际情况下可能会出现:用户当前app的数据库版本是1,而当前最新版app的数据库版本是3,此时用户升级就会直接从版本1升级到版本3,这种跳跃式的升级又该怎么处理呢?这种时候就要先创建新表,复制旧表数据,然后重命名新表。
static final Migration MIGRATION_1_3 = new Migration(1, 3) {
@Override
public void migrate(SupportSQLiteDatabase database) {
database.execSQL("CREATE TABLE IF NOT EXISTS student_new(id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL," +
"name TEXT,chinese INTEGER,english INTEGER,math INTEGER,sport INTEGER,physical INTEGER)");
database.execSQL("INSERT INTO student_new(id,name,chinese,english,math) SELECT id,name,chinese,english,math FROM student");
database.execSQL("DROP TABLE student");
database.execSQL("ALTER TABLE student_new RENAME TO student");
}
};
Original: https://blog.csdn.net/qq_52332769/article/details/122960808
Author: 圆圆的肚子
Title: Room数据库学习记录
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/816345/
转载文章受原作者版权保护。转载请注明原作者出处!