Room的基本使用

Android采用Sqlite作为数据库存储。Sqlite代码写起来繁琐且容易出错,所以开源社区里逐渐出现了各种ORM(Object Relational Mapping)库。这些开源ORM库都是为了方便Sqlite的使用,包括数据库的创建,升级,增删改查等。常见的ORM有ORMLite,GreenDAO等。Google也意识到了推出自家ORM的必要性,于是有了Room。

Room和其它ORM库一样,也是在Sqlite上提供了一层抽象。

v2-869e0a2b4cf56d21ad05f4b101ec7705_720w

关于Room的介绍将会分为三篇文章。

1.Room的基本使用:包括数据库和表的创建,以及数据的增删改查。

2.Room与LiveData+ViewModel结合使用。

3.Room数据库升级。


在介绍Room的使用之前,我们需要先明白几个概念。

Entity:这是一个Model类,对应于数据库中的一张表。Entity类是Sqlite表结构在Java类的映射。

Dao:(Data Access Objects)数据访问对象,顾名思义,我们可以通过它来访问数据。

一个Entity代表着一张表,而每张表都需要一个Dao对象,以方便对这张表进行各种操作(增删改查)

大致明白这两个概念后,我们再来看看如何在项目中使用。

1.appbuild.gradle中加入room的相关依赖。

def room_version = "2.2.0-alpha01"
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"

2.创建一个关于学生的Entity,即创建一张学生表。

我们在类文件的最上方需要加上@Entity标签,通过该标签将该类与Room中表关联起来。tableName属性可以为该表设置名字,如果不设置,则表名与类名相同。

@PrimaryKey标签用于指定该字段作为表的主键。

@ColumnInfo标签可用于设置该字段存储在数据库表中的名字并指定字段的类型。

@Ignore标签用来告诉系统忽略该字段或者方法。

@Entity(tableName = "student")
public class Student
{
    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "id", typeAffinity = ColumnInfo.INTEGER)
    public int id;

    @ColumnInfo(name = "name", typeAffinity = ColumnInfo.TEXT)
    public String name;

    @ColumnInfo(name = "age", typeAffinity = ColumnInfo.TEXT)
    public String age;

    /**
     * Room会使用这个构造器来存储数据,也就是当你从表中得到Student对象时候,Room会使用这个构造器
     * */
    public Student(int id, String name, String age)
    {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    /**
     * 由于Room只能识别和使用一个构造器,如果希望定义多个构造器,你可以使用Ignore标签,让Room忽略这个构造器
     * 同样,@Ignore标签还可用于字段,使用@Ignore标签标记过的字段,Room不会持久化该字段的数据
     * */
    @Ignore
    public Student(String name, String age)
    {
        this.name = name;
        this.age = age;
    }
}

3.针对以上学生Entity,我们需要定义一个Dao接口文件,以完成对Entity的访问。注意:在文件的上方,需要加入@Dao标签。

@Dao
public interface StudentDao
{
    @Insert
    void insertStudent(Student student);

    @Delete
    void deleteStudent(Student student);

    @Update
    void updateStudent(Student student);

    @Query("SELECT * FROM student")
    List<Student> getStudentList();

    @Query("SELECT * FROM student WHERE id = :id")
    Student getStudentById(int id);
}

4.定义好Entity和Dao后,接下去就是创建数据库了。

@Database(entities = {Student.class}, version = 1)
public abstract class MyDatabase extends RoomDatabase
{
    private static final String DATABASE_NAME = "my_db";

    private static MyDatabase databaseInstance;

    public static synchronized MyDatabase getInstance(Context context)
    {
        if(databaseInstance == null)
        {
            databaseInstance = Room
                    .databaseBuilder(context.getApplicationContext(), MyDatabase.class, DATABASE_NAME)
                    .build();
        }
        return databaseInstance;
    }

    public abstract StudentDao studentDao();
}

@Database标签用于告诉系统这是Room数据库对象。entities属性用于指定该数据库有哪些表,若需建立多张表,以逗号相隔开。version属性用于指定数据库版本号,后续数据库的升级正是依据版本号来判断的。该类需要继承自RoomDatabase,在类中,通过Room.databaseBuilder()结合单例设计模式,完成数据库的创建工作。另外,我们创建的Dao对象,在这里以抽象方法的形式返回,只需一行代码即可。

使用Room框架的其中一个好处是,如果创建过程中有问题,在编译期间编辑器就会提示你,而不用等到程序运行时。

至此,数据库和表的创建工作完成了。接下去,我们来看看Room框架下的数据库增删改查。

由于我们采用单例模式来实例化数据库,所以我们可以这样得到数据库对象:

MyDatabase myDatabase = MyDatabase.getInstance(this);

插入数据:

myDatabase.studentDao().insertStudent(new Student(name, age));

更新数据:

myDatabase.studentDao().updateStudent(new Student(id, name, age));

删除数据:

myDatabase.studentDao().deleteStudent(student);

查询所有学生:

myDatabase.studentDao().getStudentList();

查询某个学生:

myDatabase.studentDao().getStudentById(id);

这些对数据库的操作方法都是我们之前在Dao文件中已经定义好的。需要注意的是,不能直接在UI线程中执行这些操作,需要放在工作线程中进行。例如,我们可以使用AsyncTask来进行查询操作。

private class QueryStudentTask extends AsyncTask<Void, Void, Void>
{
    public QueryStudentTask()
    {

    }

    @Override
    protected Void doInBackground(Void... arg0)
    {
        studentList.clear();
        studentList.addAll(myDatabase.studentDao().getStudentList());
        return null;
    }

    @Override
    protected void onPostExecute(Void result)
    {
        super.onPostExecute(result);
        studentAdapter.notifyDataSetChanged();
    }
}

至此,我们已经学会了如何在Android项目中利用Room创建数据库,以及对数据库进行增删改查等基本操作。Room使得我们在Android中使用Sqlite变得非常容易,但对数据库的访问还需要在工作线程中进行。每次数据库发生变化,我们都需要开启一个工作线程,对数据库进行查询。那么,能否在数据库发生变化时,自动收到通知呢?答案是肯定的,通过LiveData就能实现这一点。另外,Room是如何实现数据库版本的迭代升级呢?这些内容我们将在后续文章中继续为大家讲解。

项目地址:michaelye/RoomDemo?

Room的基本使用
滚动到顶部