一 Room介绍
Room 是 SQLite的封装
SQLite: 需要写帮助类、SQL语句、执行SQL语句、创建表 → 非常非常繁琐
Room(SQLite的封装): 面向注解开发 @Entity @Dao @Database → 方便
通过在实体类上加注解@Entity,让实体类相当于一张表
通过在Dao接口上加注解@Dao,就可以让dao轻松地完成增删改查
创建一个类继承RoomDatabase,加注解@Database,轻松地建数据库和建表
二 案例代码
用Room完成如下增删改查功能
1 导入依赖,同步
def room_version = "2.2.0-alpha01"
implementation "androidx.room:room-runtime:$room_version";
annotationProcessor "androidx.room:room-compiler:$room_version"
2 创建一个实体类,加注解@Entity
package room;
import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.Ignore;
import androidx.room.PrimaryKey;
//一张表
//@Entity(tableName = "student_table"):tableName给表起别名,不写tableName表名就和java 类名一样
@Entity
public class Student {
@PrimaryKey(autoGenerate = true)//主键自增
@ColumnInfo(name = "_id")//定义数据库列名为 _id
private int id;
private String name;
private int age;
public Student() {
}
@Ignore
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Ignore
public Student(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
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 int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
3 创建一个Dao接口,加注解@Dao
package room;
import androidx.room.Dao;
import androidx.room.Delete;
import androidx.room.Insert;
import androidx.room.Query;
import androidx.room.Update;
import java.util.List;
@Dao
public interface StudentDao {
//新增(可变参数)
@Insert
void insertStudents(Student... students);
//条件删除
@Delete
void deleteStudents(Student... students);
//修改(可变参数)
@Update
void updateStudents(Student... students);
//条件查询多个
@Query("select * from student where name=:name")
List<Student> getStudents(String... name);
//条件查询1个
@Query("select * from student where _id=:id")
Student getStudent(int... id);
//查询所有
@Query("select * from student")
List<Student> getAllStudents();
//删除所有 → '所有'的只能用@Query,@Query可以编写任意的sql语句
@Query("DELETE FROM student")
void deleteAllStudents();
}
4 创建类继承RoomDatabase,加注解@Database
package room;
import android.content.Context;
import androidx.room.Database;
import androidx.room.Room;
import androidx.room.RoomDatabase;
//数据库关联之前的表和增删改查数据信息
@Database(entities = {Student.class},version = 2,exportSchema = false)
public abstract class StudentDatabase extends RoomDatabase {
//单例模式 返回db
private static StudentDatabase INSTANCE;
//用户只需要操作dao,必须暴露dao,dao被用户拿到后,就能进行增删改查了
public abstract StudentDao getStudentDao();
public static synchronized StudentDatabase getInstance(Context context){
if(INSTANCE == null){
INSTANCE = Room.databaseBuilder
(context.getApplicationContext(),StudentDatabase.class,"say.db")
//数据库默认是异步线程
//慎用:强制开启 主线程也可以操作数据库(测试可以用,真实环境不要用)
.allowMainThreadQueries()
.build();
}
return INSTANCE;
}
}
5 获取数据库的实例获取dao调用方法
package com.example.mydatastroe;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import java.util.ArrayList;
import java.util.List;
import room.Student;
import room.StudentDatabase;
public class MainActivity4 extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main4);
}
//新增:2个学生
public void insert(View view) {
//id 自增不用赋值
Student student1 = new Student("小蓝", 12);
Student student2 = new Student("小紫", 8);
StudentDatabase.getInstance(this).getStudentDao().
insertStudents(student1,student2);
}
//条件删除:删除id为1的学生
public void delete(View view) {
Student student = new Student();
student.setId(1);
StudentDatabase.getInstance(this).getStudentDao().deleteStudents(student);
}
//修改id为3的学生为 白老板 100岁
public void update(View view) {
Student student = new Student(3,"白老板",100);
StudentDatabase.getInstance(this).getStudentDao().updateStudents(student);
}
//条件查询:查询姓名为"小蓝"的学生
public void queryMany(View view) {
Log.e("cs", "-----------------条件查询多个----------------------");
List<Student> list = StudentDatabase.getInstance(this).getStudentDao().getStudents("小蓝");
for (Student student : list) {
Log.e("cs", student.toString());
}
}
//条件查询:查询id为2的学生
public void queryOne(View view) {
Log.e("cs", "-----------------条件查询1个----------------------");
Student student = StudentDatabase.getInstance(this).getStudentDao().getStudent(2);
Log.e("cs", student.toString());
}
//查询所有
public void queryAll(View view) {
Log.e("cs", "-----------------查询所有----------------------");
List<Student> list = StudentDatabase.getInstance(this).getStudentDao().getAllStudents();
for (Student student : list) {
Log.e("cs", student.toString());
}
}
//删除所有
public void deleteAll(View view) {
StudentDatabase.getInstance(this).getStudentDao().deleteAllStudents();
Log.e("cs", "已删除所有数据");
}
}
附上布局的文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity4">
<Button
android:text="增"
android:onClick="insert"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:text="删"
android:onClick="delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:text="改"
android:onClick="update"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:text="查多"
android:onClick="queryMany"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:text="查1"
android:onClick="queryOne"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:text="查所有"
android:onClick="queryAll"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:text="删所有"
android:onClick="deleteAll"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
启动程序之后,Room框架会自动生成这2个文件

效果
总结使用步骤
1 导入依赖,同步
//Room的支持
def room_version = "2.2.0-alpha01"
implementation "androidx.room:room-runtime:$room_version";
annotationProcessor "androidx.room:room-compiler:$room_version"
2 创建一个实体类Student,加注解@Entity就相当于一张表
3 创建一个接口StudentDao,加注解@Dao就可以完成增删改查
(Dao: database access object)
4 创建抽象类StudentDatabase继承RoomDatabase,加注解@Database相当于是数据库
单例模式返回db (创建数据库)
暴露dao
5 获取数据库的实例获取dao调用方法
StudentDatabase.getInstance(this).getStudentDao().getAllStudents()
三 报错及改正
3.1 @Ignore
错误:
错误: Room cannot pick a constructor since multiple constructors are suitable. Try to annotate unwanted constructors with @Ignore.
改正:
实体类不能有多个主构造方法,解决办法是只留一个常用的构造方法,剩下的构造方法加注解 @Ignore
3.2 allowMainThreadQueries()
错误:
IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time
改正:
调用这个方法让主线程也可以操作数据库
3.3 查询方法参数错误
错误:
错误: Query method parameters should either be a type that can be converted into a database column or a List / Array that contains such type. You can consider adding a Type Adapter for this.
百度翻译一下:
查询方法参数应该是可以转换为数据库列的类型,或者是包含此类类型的列表/数组。可以考虑为此添加类型适配器。
错误代码如下
用@Query查询的时候,参数传的实体类,实体类不能转化成数据库里的列!
改正: