Room Database完全使用手册

news/2024/7/4 3:34:59

前言

Android数据持久层直接使用SQLite很麻烦,Google官方推出了Room, Google对Room的定义: The Room persistence library provides an abstraction layer over SQLite to allow fluent database access while harnessing the full power of SQLite. Room是SQLite之上的一个抽象层,通过Room层来摆脱,繁琐的数据库操作,包括创建、更新数据库、表以及进行增删查改等。

Room数据库结构

如下图,Room数据库包含三个对象:

1、Entity : 对应数据库中的表,可以使用Entity注解将一个类变成数据库中的一张表结构。

2、DAO : 全称Database Access

Object,定义了对数据库中数据的读写等操作,DAO中可以使用SQL语句来操作数据库。

3、RoomDatabase : 数据库持有类,用于创建数据库或者连接到数据库。内部包含DAO和Entity。

上面总体说了Room数据库的三个对象,下面分别介绍三个对象的作用和使用方法。

Entity

Room Database中的Entity表示一张数据表结构,一个Entity实例就是表中的一行,如定义一个Person类的Entity。

@Entity
public class Person{@PrimaryKeypublic int id;public String firstName;public String lastName;
}
复制代码

当有两个Person对象在表中时,表中的数据如下:

其中Person和Entity及数据库的关系如下所示:

重点:

1、一个Entity对象代表数据表中的一行,一个Entity类代表一张数据表。

2、Entity中的成员变量都是数据表中的列。

3、一个Java类定义成Entity只要加上Entity注解就可以了。

Entity的使用

1、定义一个Entity

@Entity(tableName = "person_table")
public class Person{@PrimaryKeypublic int id;public String firstName;public String lastName;
}
复制代码

如果想给Entity命名可以在@Entity注解的后面加上(tableName = "person_table"),如果不加会使用默认命名,上面的id,firstName, lastName都定义成了public类型,是为了数据库能够有操作这些数据的权限,也可以选择将这些都设置成private类型,然后通过setter和getter来操作。

2、定义主键

每一个Entity至少定义一个主键(primary key),哪怕Entity中只有一个变量也要将这个变量定义为主键,在Room数据库中使用注解 @PrimaryKey 来定义主键,@PrimaryKey 的使用方式有两种一种是在类变量前面加,如果主键比较复杂可以加在@Entity注解的后面。

@Entity(primaryKeys = {"firstName", "lastName"})
public class User {public String firstName;public String lastName;
}
复制代码

3、改变属性列名

和改变表名称tableName一样,可以改变表中的列名称,使用 @ColumnInfo来改变列的名称。如果不改的话默认使用变量名的小写形式。

@Entity(tableName = "person_table")
public class Person {@PrimaryKeypublic int id;@ColumnInfo(name = "first_name")public String firstName;@ColumnInfo(name = "last_name")public String lastName;
}
复制代码

4、使某些变量不生成数据表中的字段

由上面可知当一个类前加了Entity注解后类中的所有成员变量都会生成表中的属性列,如果我们不希望某个变量生成表中的属性列,可以使用注解 @Ignore。

@Entity
public class Person {@PrimaryKeypublic int id;public String firstName;public String lastName;@IgnoreBitmap picture;
}
复制代码

如果有类继承上面的Person类,并且不想picture生成数据表中的列,那么可以ignoredColumns

@Entity(ignoredColumns = "picture")
public class RemotePerson extends Person {@PrimaryKeypublic int id;public boolean hasVpn;
}
复制代码

5、两个数据表关联

SQLite是关系数据库,可以明确两个对象间的关系,大多数的关系数据库都可以指定表之间的关联,但是Room数据库不能够之间指定两个表之间的关系,但是可以通过@ForeignKey注解来进行表的关联。

@Entity(foreignKeys = @ForeignKey(entity = Person.class,parentColumns = "id",childColumns = "user_id"))
public class Book {@PrimaryKeypublic int bookId;public String title;@ColumnInfo(name = "user_id")public int userId;
}
复制代码

6、嵌套Entity

如果定义的Entity类里面有个对象,并且希望定义的Entity中的表列字段包含Entity类对象中的变量,可以在Entity类对象中加@Embedded标注。

public class Address {public String street;public String state;public String city;@ColumnInfo(name = "post_code")public int postCode;
}@Entity
public class Person{@PrimaryKeypublic int id;public String firstName;@Embeddedpublic Address address;
}
复制代码

这样Person表中的列字段有id, firstName, street, state, city,和 post_code.

DAO

在DAO(data access object)中,可以使用SQL语句进行对数据库的操作并且将这些语句与Java中方法关联调用,编译器会检查SQL语句并且通过注解生成对应的查询语句,例如@Insert。

注意:

1、DAO必现是抽象类或者接口

2、所有的查询语句必须在单独的线程里面执行。

DAO的使用

可以使用sql中的语句来实现DAO的操作。

1、插入数据

当在方法前使用@Insert注解时,Room数据库会将方法中的所有参数都插入到数据表中。

@Dao
public interface MyDao {@Insert(onConflict = OnConflictStrategy.REPLACE)public void insertUsers(User... users);@Insertpublic void insertBothUsers(User user1, User user2);@Insertpublic void insertUsersAndFriends(User user, List<User> friends);
}
复制代码

当@Insert 方法只插入一个参数时,插入会返回long数据代表插入的对象在数据表中的行号,当插入一个数组或者集合形式的数据时,会返回long数组或者集合。 2、更新数据

@Update标注的方法会查找表中与所给数据主键一样的数据进行更新。

@Dao
public interface MyDao {@Updatepublic void updateUsers(User... users);
}
复制代码

3、查询数据

@Query 标注的查询方法是使用最多的方法,每个查询方法在编译期间就会被验证是否正确,如果错误就会报错,不会在运行时再提示失败。在

@Dao
public interface MyDao {@Query("SELECT * FROM user")public User[] loadAllUsers();
}
复制代码

如果存在查询语法错误,或者数据库中不存在user表,Room数据库会在编译时提示错误信息。 也可以使用SQL语句实现复杂的查询

@Dao
public interface MyDao {@Query("SELECT * FROM user WHERE age BETWEEN :minAge AND :maxAge")public User[] loadAllUsersBetweenAges(int minAge, int maxAge);@Query("SELECT * FROM user WHERE first_name LIKE :search " +"OR last_name LIKE :search")public List<User> findUserWithName(String search);
}
复制代码

4、查询列表中的数据并返回子列表

有时候并不需要将查询数据的所有字段都返回,大部分时候只需要返回查询数据的一个子域。下面实现返回查询的一个子域。

public class NameTuple {@ColumnInfo(name = "first_name")public String firstName;@ColumnInfo(name = "last_name")public String lastName;
}
复制代码

然后查询返回子域中的字段

@Dao
public interface MyDao {@Query("SELECT first_name, last_name FROM user")public List<NameTuple> loadFullName();
}
复制代码

RoomDatabase

上面已经介绍了DAO和Entity,Entity定义表,DAO定义对表中数据进行操作,RoomDatabase包含了DAO,并且提供创建和连接数据库的方法。

创建Room database

创建Room database包括三个步骤: 1、创建继承RoomDatabase的抽象类。

2、在继承的类前使用注解@Database。

3、申明数据库结构的Entity,并且设置数据库的版本号。

@Database(entities = {Word.class}, version = 1)//申明Entity和数据库的版本号
public abstract class WordRoomDatabase extends RoomDatabase { public abstract WordDao wordDao();//创建DAO的抽象类private static WordRoomDatabase INSTANCE;//创建单例static WordRoomDatabase getDatabase(final Context context) {if (INSTANCE == null) {synchronized (WordRoomDatabase.class) {if (INSTANCE == null)    {INSTANCE = Room.databaseBuilder(context.getApplicationContext(),WordRoomDatabase.class, "word_database").addCallback(sOnOpenCallback).fallbackToDestructiveMigration().build();                }}}return INSTANCE;}private static RoomDatabase.Callback sOnOpenCallback =new RoomDatabase.Callback(){@Overridepublic void onOpen (@NonNull SupportSQLiteDatabase db){super.onOpen(db);initializeData();}};}
复制代码

注意: 1、编译时会检查SQL语句是否正确

2、不要在主线程中进行数据库操作

3、RoomDatabase最好使用单例模式

最后上一张Android在使用Room数据库时和Room数据库交互的图

application从RoomDatabase中获取DAO实例,并且通过DAO中定义的方法来操作数据库中Entity。获取设置entity的数据。

Room database Migration

当升级Android应用的时候,有时需要更改数据库中数据的结构,要用户升级应用的时候保持原有的数据不变,使用数据库移植Migration是必须的。在Room数据库中Room persistence library库提供了升级数据库时保存用户数据的方法。 使用方法 定义Migration对象,每个对象包含数据库的开始版本号和结束版本号。

    static final Migration MIGRATION_1_2 = new Migration(1, 2) {@Overridepublic void migrate(SupportSQLiteDatabase database) {//这里面实现更改数据表结构的方法}};
复制代码

如上实现一个Migration对象,重写migrate方法,在migrate方法中实现升级时要进行的操作。

    static final Migration MIGRATION_2_3 = new Migration(2, 3) {@Overridepublic void migrate(SupportSQLiteDatabase database) {database.execSQL("ALTER TABLE users "+ " ADD COLUMN last_update INTEGER");}};
复制代码

如果我们数据库要从版本1,升级到版本库,就要定义MIGRATION_1_2 ,MIGRATION_2_3 ,MIGRATION_3_4 ,MIGRATION_1_4 并且改写单例方法。

    public static UsersDatabase getInstance(Context context) {synchronized (sLock) {if (INSTANCE == null) {INSTANCE = Room.databaseBuilder(context.getApplicationContext(),UsersDatabase.class, "Sample.db").addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4, MIGRATION_1_4).build();}return INSTANCE;}}
复制代码

当然不一定非要定义MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4, MIGRATION_1_4这么多,也可以一次从MIGRATION_1_4,跳过中间的MIGRATION,但是如果不提供足够的MIGRATION,从当前版本变到最新版本,Room数据库会清楚原来的数据重写创建。

参考文献

1、developer.android.com/training/da…

2、codelabs.developers.google.com/codelabs/an…

我的csdn

blog.csdn.net/u013309870/…


http://lihuaxi.xjx100.cn/news/236344.html

相关文章

软件工程技术基础-(软件复用技术)

软件可重用问题&#xff0c;包括源程序代码重用、静态库重用和组建重用。 源程序代码重用是直接将其他项目或系统开发完成的代码复制过来&#xff0c;直接使用。 限制源程序代码重用技术使用的关键因素是要考虑代码的语言实现&#xff0c;以及源代码 公开可能带来的知识产权问题…

php监听订单状态,ecshop数据库订单状态判断

order_info 表刚下完订单order_status 0shipping_status 0pay_status 0取消order_status 2shipping_status 0pay_status 0确认order_status 1shipping_status 0pay_status 0已付款order_status 1shipping_status 0pay_status 2配货中order_status 1shipping_status 3pay_status…

firefox下的调试工具

2019独角兽企业重金招聘Python工程师标准>>> vue-devtools https://addons.mozilla.org/en-US/firefox/user/13100848/ 转载于:https://my.oschina.net/u/3371661/blog/3003299

小编带你进入强如 Disruptor 也发生内存溢出?

前言OutOfMemoryError 问题相信很多朋友都遇到过&#xff0c;相对于常见的业务异常&#xff08;数组越界、空指针等&#xff09;来说这类问题是很难定位和解决的。 本文以最近碰到的一次线上内存溢出的定位、解决问题的方式展开&#xff1b;希望能对碰到类似问题的同学带来思路…

PHP上传文件函数move_upload,如何使用php中move_uploaded_file函数

我们平时上传的文件保存在临时文件夹中&#xff0c;例如/ tmp&#xff0c;但临时文件夹的内容在一段时间后会被删除&#xff0c;因此为了将来要使用上传文件&#xff0c;需要将内容保存在不太可能被任意删除的专用目录中&#xff0c;这时就需要使用move_uploaded_file函数&…

Dubbo2.6.5+Nacos注册中心(代替Zookeeper)

在上一节的小栗子的基础上&#xff0c;只需要更改两个地方 第一个&#xff1a;父工程的pom依赖增加 <!-- Dubbo Nacos registry dependency --><dependency><groupId>com.alibaba</groupId><artifactId>dubbo-registry-nacos</artifactId>…

oracle停止一切进程,oracle启动/停止的几种方法以及 启动和停止过程中出错的解决办法...

一、启动几种方法&#xff1a;1、sqlplus /nologconnect /as sysdbastartup2、sqlplus /nologconnect /as sysdbastartup nomountalter database mountalter database open在以上两种方法中&#xff0c;1方法中的startup相当于2方法中的startup nomountalter database mountalt…

Web.XML文件中关于代码提示的一些问题

1. 问题描述 在进行ssm的整合时&#xff0c;我发现在web.xml文件中里按了alt/以后没有下面的提示&#xff1a;这样真的很不爽。。。于是弄了半天&#xff08;主要是等着&#xff09;终于解决了&#xff0c;特此写篇博客记录下。 2. 解决方案 在eclipse中安装Spring IDE的插件&a…