Room来源
Android采用Sqlite作为数据库存储。由于Sqlite代码写起来繁琐且容易出错,因此,开源社区逐渐出现了各种ORM(Object Relational Mapping)库。常见的有ORMLite, GreenDAO等。Google也意识到推出自家ORM库的必要性,于是有了Room,Room同其他ORM库一样,也是在Sqlite上提供了一层封装。
Room 主要组件
Room
包含三个主要组件:- (1)(Entity)数据实体,用于表示应用的数据库中的表;
- (2)(Dao)数据访问对象 (Data Access Objects),提供您的应用可用于插入、删除、更新和查询数据库中的数据的方法。
- (3)Database数据库类,用于保存数据库并作为应用持久性数据底层连接的主要访问点;
三者关系
Entity:一个Entity对应数据库中的一张表。Entity类是Sqlite表结构对Java类的映射,在Java中可以看作一个Model类。
Dao:数据访问对象(Data Access Objects),我们通过它来访问数据。
一个Entity代表一张表,而每张表都需要一个Dao对象,用于对表进行增删改查;
Room数据库在被实例化之后我们就可以通过数据库实例获取Dao对象,然后通过Dao进行数据库操作。
一、添加依赖
def room_version = "2.4.2"
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"
二、创建实体类,一个实体类对应数据库中的一张表
package com.example.savedata;
import androidx.room.Entity;
import androidx.room.Ignore;
import androidx.room.PrimaryKey;
@Entity
public class Student {
@PrimaryKey(autoGenerate = true)
public int id;
public String stuName;
public int stuAge;
public int score;
@Ignore
public Student(int id, String stuName, int stuAge, int score) {
this.id = id;
this.stuName = stuName;
this.stuAge = stuAge;
this.score = score;
}
//Ignore亦可注解字段,让Room忽略此方法或者字段
//由于Room只能识别一个构造器,如果需要定义多个构造器,可以使用Ignore注解让Room忽略这个构造器
//Room不会持久化被注解Ignore标记过的字段
public Student(String stuName, int stuAge, int score) {
this.stuName = stuName;
this.stuAge = stuAge;
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", stuName='" + stuName + '\'' +
", stuAge=" + stuAge +
", score=" + score +
'}';
}
}
三、数据访问对象 (DAO)
- 定义数据访问对象 (
DAO
),提供可用于插入、删除、更新和查询数据库中的数据的方法
package com.example.savedata;
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
public void insertStu(Student... students);
@Delete
public void deleteStu(Student... students);
@Update
public void updateStu(Student... students);
//查询所有
@Query("select * from student")
public List<Student> queryStu();
@Query("select * from student where stuName=:name")
public List<Student> queryStuByName(String name);
@Query("select * from student where id=:id")
public Student queryStuById(int id);
}
四、数据库类
定义数据库配置,并作为应用对持久性数据的主要访问点。
数据库类必须满足以下条件:
(1)该类必须带有 @Database 注解,该注解包含列出所有与数据库关联的数据实体的 entities 数组;
(2)该类必须是一个抽象类,用于扩展 RoomDatabase;
(3)对于与数据库关联的每个 DAO 类,数据库类必须定义一个具有零参数的抽象方法,并返回 DAO 类的实例。
注意:
(1)如果您的应用在单个进程中运行,在实例化 AppDatabase 对象时应遵循单例设计模式。每个 RoomDatabase 实例的成本相当高,而您几乎不需要在单个进程中访问多个实例;
(2)如果您的应用在多个进程中运行,请在数据库构建器调用中包含 enableMultiInstanceInvalidation()。这样,如果您在每个进程中都有一个 AppDatabase 实例,可以在一个进程中使共享数据库文件失效,并且这种失效会自动传播到其他进程中 AppDatabase 的实例。
package com.example.savedata;
import android.content.Context;
import androidx.room.Database;
import androidx.room.Room;
import androidx.room.RoomDatabase;
@Database(entities = {Student.class},version = 1)
public abstract class StuDatabase extends RoomDatabase {
private static final String DATABASE_NAME = "student_db";
private static StuDatabase databaseInstance;
//结合单例模式完成创建数据库实例
public static synchronized StuDatabase getDatabaseInstance(Context context) {
if (databaseInstance == null) {
databaseInstance = Room.databaseBuilder(context.getApplicationContext(),
StuDatabase.class,DATABASE_NAME).build();
}
return databaseInstance;
}
//将第四步创建的Dao对象以抽象方法的形式返回
public abstract StudentDao getStudentDao();
}
五、界面
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<EditText
android:id="@+id/etName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="请输入姓名"
android:inputType="textPersonName"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/etAge"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="请输入年龄"
android:inputType="textPersonName"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/etName" />
<EditText
android:id="@+id/etScore"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="请输入成绩"
android:inputType="textPersonName"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/etAge" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.24" />
<Button
android:id="@+id/btnInsertData"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="插入数据"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/guideline2" />
<Button
android:id="@+id/btnDeleteData"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="删除数据"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.501"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btnInsertData" />
<Button
android:id="@+id/btnQueryData"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="查询数据"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btnDeleteData" />
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.5" />
<TextView
android:id="@+id/tvData"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="数据表中的数据"
android:gravity="center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/guideline4" />
</androidx.constraintlayout.widget.ConstraintLayout>
六、实现(对数据的操作必须在子线程中,否则程序崩溃)
package com.example.savedata;
import androidx.appcompat.app.AppCompatActivity;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private EditText etName;
private EditText etAge;
private EditText etScore;
private Button btnInsertData;
private Button btnDeleteData;
private Button btnQueryData;
private TextView tvData;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
btnInsertData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
insertData();
}
});
btnDeleteData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
deleteData();
}
});
btnQueryData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
queryData();
}
});
}
private void insertData() {
new Thread(new Runnable() {
@Override
public void run() {
String stuName = etName.getText().toString();
int stuAge = Integer.parseInt(etAge.getText().toString());
int score = Integer.parseInt(etScore.getText().toString());
Student student1= new Student(stuName,stuAge,score);
StudentDao dao = StuDatabase.getDatabaseInstance(MainActivity.this).getStudentDao();
dao.insertStu(student1);
}
}).start();
}
private void deleteData() {
}
private void queryData() {
new Thread(new Runnable() {
@Override
public void run() {
StudentDao dao = StuDatabase.getDatabaseInstance(MainActivity.this).getStudentDao();
List<Student> students = dao.queryStu();
String studentsAll ="";
for(int i =0;i<students.size();i++){
String studentInfo = students.get(i).toString();
studentsAll = studentsAll+"\n"+studentInfo;
}
dispalayData(studentsAll);
}
}).start();
}
private void dispalayData(String studentsAll) {
runOnUiThread(new Runnable() {
@Override
public void run() {
tvData.setText(studentsAll);
}
});
}
private void initView() {
etName= findViewById(R.id.etName);
etAge = findViewById(R.id.etAge);
etScore = findViewById(R.id.etScore);
btnInsertData = findViewById(R.id.btnInsertData);
btnDeleteData = findViewById(R.id.btnDeleteData);
btnQueryData = findViewById(R.id.btnQueryData);
tvData = findViewById(R.id.tvData);
}
}