android Room数据库框架使用流程整理

前言

    因为遇到需求需要保存数据到本地数据库,一起开发的同事选用了Room数据库框架移植到项目中,于是我也只能去学习使用这种框架。了解之后发现这个框架建库、建表、数据库升级等操作都十分简单,很适合怕麻烦的攻城狮们使用。

正文

    1.建表

      这里以常用的存储用户信息的user表为例:

      

/**
 * @Description: 存储用户信息到本地数据库
 * @author: jesse_android
 * @date: 2019/4/19
 */
@Entity(tableName = "user")
public class UserInfo {

    @PrimaryKey(autoGenerate = true)
    private int id;

    private int userId;
    private String mobile;
    private String nickname;
    private String avatar;
    private String category;
    private String instituteId;
    private int role;
    private int certify;//认证状态 0未认证 1已认证
    private int partner;//是否是合伙人 0不是 1是

    public UserInfo(int userId, String mobile) {
        this.userId = userId;
        this.mobile = mobile;
    }

    @Ignore
    public UserInfo(){}

    @Ignore
    public UserInfo(OrgLoginBean loginBean) {
        this.userId = loginBean.getData().getUserId();
        this.mobile = loginBean.getData().getMobile();
        this.nickname = loginBean.getData().getNickname();
        this.avatar = loginBean.getData().getAvatar();
        this.certify = loginBean.getData().getCertify();
        this.partner = loginBean.getData().getPartner();
    }

    @Ignore
    public UserInfo(int userId, String mobile, String nickname, String avatar, String category, String instituteId) {
        this.userId = userId;
        this.mobile = mobile;
        this.nickname = nickname;
        this.avatar = avatar;
        this.category = category;
        this.instituteId = instituteId;
    }

    @Ignore
    public UserInfo(int userId, String mobile, String nickname, String avatar, int certify) {
        this.userId = userId;
        this.mobile = mobile;
        this.nickname = nickname;
        this.avatar = avatar;
        this.certify = certify;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getUserId() {
        return userId;
    }

    public void setUserId(int userId) {
        this.userId = userId;
    }

    public String getMobile() {
        return mobile;
    }

    public void setMobile(String mobile) {
        this.mobile = mobile;
    }

    public String getNickname() {
        return nickname;
    }

    public void setNickname(String nickname) {
        this.nickname = nickname;
    }

    public String getAvatar() {
        return avatar;
    }

    public void setAvatar(String avatar) {
        this.avatar = avatar;
    }

    public String getCategory() {
        return category;
    }

    public void setCategory(String category) {
        this.category = category;
    }

    public String getInstituteId() {
        return instituteId;
    }

    public void setInstituteId(String instituteId) {
        this.instituteId = instituteId;
    }

    public int getRole() {
        return role;
    }

    public void setRole(int role) {
        this.role = role;
    }

    public int getCertify() {
        return certify;
    }

    public void setCertify(int certify) {
        this.certify = certify;
    }

    public int getPartner() {
        return partner;
    }

    public void setPartner(int partner) {
        this.partner = partner;
    }

    @Override
    public String toString() {
        return "UserInfo{" +
                "id=" + id +
                ", userId=" + userId +
                ", mobile='" + mobile + '\'' +
                ", nickname='" + nickname + '\'' +
                ", avatar='" + avatar + '\'' +
                ", category='" + category + '\'' +
                ", instituteId='" + instituteId + '\'' +
                ", role=" + role +
                ", certify=" + certify +
                ", partner=" + partner +
                '}';
    }
}

细节解析:

1.@Entity(tableName = "user")--定义表明为user;

2.@PrimaryKey(autoGenerate = true)--将下方字段设置为主键并且自增;autoGenerate = true--自增;

3.@Ignore--编译时忽略下方的构造方法;(一个实体类只允许有一个构造方法进入编译,否则报错。因此只能留一个构造方法,其余的都要加上@Ignore标签!!!加上这个标签并不会影响你正常调用)

2.建库

    为什么先说建表再说建库?因为建库的时候会用到表。

    

@Database(entities = {UserInfo.class}, version = 1, exportSchema = false)
public abstract class CoursewareDataBase extends RoomDatabase {

    private static final String DB_NAME = "CoursewareDatabase.db";
    private static volatile CoursewareDataBase instance;

    static synchronized CoursewareDataBase getInstance(Context context) {
        if (instance == null) {
            instance = create(context);
        }
        return instance;
    }

    private static CoursewareDataBase create(final Context context) {
        return Room.databaseBuilder(context, CoursewareDataBase.class, DB_NAME)
                .addMigrations(migration_1_2)
                .addMigrations(migration_2_3)
                .addMigrations(migration_3_4)
                .addMigrations(migration_4_5)
                .build();
    }

    //@{版本号升级后一定要加migration
    private static Migration migration_1_2 = new Migration(1, 2) {
        @Override
        public void migrate(@NonNull SupportSQLiteDatabase database) {
            database.execSQL("ALTER TABLE user ADD certify INTEGER NOT NULL DEFAULT 0");
        }
    };

    private static Migration migration_2_3 = new Migration(2, 3) {
        @Override
        public void migrate(@NonNull SupportSQLiteDatabase database) {
            database.execSQL("ALTER TABLE video_list ADD stage TEXT DEFAULT ''");
        }
    };
    private static Migration migration_3_4 = new Migration(3, 4) {
        @Override
        public void migrate(@NonNull SupportSQLiteDatabase database) {
            database.execSQL("ALTER TABLE video_list ADD views INTEGER NOT NULL DEFAULT 0");
        }
    };
    private static Migration migration_4_5 = new Migration(4, 5) {
        @Override
        public void migrate(@NonNull SupportSQLiteDatabase database) {
            database.execSQL("ALTER TABLE user ADD partner INTEGER NOT NULL DEFAULT 0");
        }
    };
    //@}

    public abstract UserDao getUserDao();
}

细节解析:

1.@Database(entities = {UserInfo.class}, version = 1, exportSchema = false)--声明该类作为一个本地数据库;entities={}--你建的表的实体类必须在花括号中声明;version = 1--当前数据库版本为1,要升级数据库版本的话,需要填入比当前数字更大的数字,比如2;exportSchema = false--如果设置为true,在app目录下会生成一个Schema文件夹,里面会生成数据库版本.json文件,设置为true有报错风险,建议设为false。

2.public abstract class CoursewareDataBase extends RoomDatabase--注意这里必须要设置该类为抽象类,然后继承RoomDataBase类;

3.创建数据库、数据库版本升级:

private static CoursewareDataBase create(final Context context) {
        return Room.databaseBuilder(context, CoursewareDataBase.class, DB_NAME)
                .addMigrations(migration_1_2)
                .addMigrations(migration_2_3)
                .addMigrations(migration_3_4)
                .addMigrations(migration_4_5)
                .build();
    }

    //@{版本号升级后一定要加migration
    private static Migration migration_1_2 = new Migration(1, 2) {
        @Override
        public void migrate(@NonNull SupportSQLiteDatabase database) {
            database.execSQL("ALTER TABLE user ADD certify INTEGER NOT NULL DEFAULT 0");
        }
    };

--版本升级照着这样写就行了,不用我多说应该能看懂,如果是初始数据库版本,则不用写addMigrations,直接return Room.databaseBuilder(context, CoursewareDataBase.class, DB_NAME).build();即可。

4.public abstract UserDao getUserDao();--需要用到的Dao文件必须在类中声明。

3.创建Dao文件

@Dao
public interface UserDao {

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    void insertUser(UserInfo... userinfo);

    @Query("SELECT * FROM user")
    List<UserInfo> queryAll();

    @Query("SELECT * FROM user where userId = :userId")
    UserInfo queryUser(int userId);

    @Query("DELETE FROM user where userId = :userId")
    void deleteUser(int userId);

}

细节解析:

1.@Dao--声明该类为Dao文件(用来操作表增删改查的文件);

2.@Insert(onConflict = OnConflictStrategy.REPLACE)--插入一条新数据到表中;onConflict = OnConflictStrategy.REPLACE--如果插入的新数据在表中已经存在,即如果遇上数据冲突的情况,新数据直接替换旧数据;

3.@Query("SELECT * FROM user")--@Query标签后方的括号里可用的语句不仅仅限于查询语句,其他所有SQL语句都可以写在里面,比如你可以使用这个标签做delete操作:@Query("DELETE FROM user where userId = :userId");--:userId 表示使用下方传入的userId参数。

4.使用Dao文件操作数据库

    

private CoursewareDataBase coursewareDataBase;
private UserDao userDao;

coursewareDataBase = CoursewareDataBase.getInstance(context);
userDao = coursewareDataBase.getUserDao();

        new Thread(new Runnable() {
            @Override
            public void run() {
                List<UserInfo> userInfoList =  userDao.queryAll();
            }
        }).start();

这里特别要注意的就是userDao.queryAll()这句代码必须放在子线程中,否则会报错。以上是以调用queryAll方法作为例子,调用其他userDao中的方法同样。

附上博主使用的room项目依赖添加代码:

implementation('android.arch.persistence.room:runtime:1.0.0') {
    exclude group: 'com.android.support'
}
annotationProcessor "android.arch.persistence.room:compiler:1.0.0"

结语

    从创建到数据库升级到使用Dao文件操作数据库,流程相当简单,这就是Room这个框架的优势,但是只能在子线程中进行数据库操作是它的硬伤,如果你能接受这一点的话,那么Room也不失为一个好的android本地数据库框架。

    如果这篇文章对你有帮助,点下免费的赞和关注鼓励一下吧,这些都是我更博的动力,谢啦~

    有不懂或者使用过程中遇到什么问题的,欢迎下方留言。

发布了73 篇原创文章 · 获赞 30 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/yonghuming_jesse/article/details/104799022