Room数据库学习记录

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/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球