android room数据库简单使用

news/2024/11/6 11:25:48/

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进行数据库操作。

Room 库架构的示意图

 

一、添加依赖

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;@Ignorepublic 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;}@Overridepublic 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 {//插入数据@Insertpublic void insertStu(Student... students);@Deletepublic void deleteStu(Student... students);@Updatepublic 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"><EditTextandroid: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" /><EditTextandroid: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" /><EditTextandroid: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.Guidelineandroid:id="@+id/guideline2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="horizontal"app:layout_constraintGuide_percent="0.24" /><Buttonandroid: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" /><Buttonandroid: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" /><Buttonandroid: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.Guidelineandroid:id="@+id/guideline4"android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="horizontal"app:layout_constraintGuide_percent="0.5" /><TextViewandroid: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;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initView();btnInsertData.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {insertData();}});btnDeleteData.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {deleteData();}});btnQueryData.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {queryData();}});}private void insertData() {new Thread(new Runnable() {@Overridepublic 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() {@Overridepublic 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() {@Overridepublic 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);}}


http://www.ppmy.cn/news/68091.html

相关文章

什么是VLAN?为什么要划分VLAN?

VLAN(Virtual Local Area Network)即虚拟局域网&#xff0c;是将一个物理的LAN在逻辑上划分成多个广播域的通信技术。每个VLAN是一个广播域&#xff0c;VLAN内的主机间可以直接通信&#xff0c;而VLAN间则不能直接互通。这样&#xff0c;广播报文就被限制在一个VLAN内。 一、为…

蓝桥杯模块学习3——蜂鸣器与继电器

第一章 硬件部分 1.1 电路的组成部分 1.1.1 译码器和锁存器 具体可回顾之前LED灯的文章&#xff1a; https://blog.csdn.net/weixin_63568691/article/details/130660096 1.1.2 ULN2003达林顿管 原理图&#xff1a; 功能&#xff1a; &#xff08;1&#xff09;改变电路特性…

栈和队列的实现

栈 栈的概念 栈也是线性表的一种&#xff0c;但是栈只允许在固定的一端进行插入与删除数据&#xff0c;而进行插入与删除的一端同意称为栈顶&#xff0c;而另一端就称为栈底。简称&#xff1a;后进先出。 压栈&#xff08;push&#xff09;&#xff1a;将数据插入栈顶。 出…

ANR实战案例 2 - 不同线程状态ANR示例

系列文章目录 提示&#xff1a;这里可以添加系列文章的所有文章的目录&#xff0c;目录需要自己手动添加 例如&#xff1a;第一章 Python 机器学习入门之pandas的使用 文章目录 系列文章目录前言一、Blocked状态示例1.启动初始化阻塞案例trace1.tx 2.ConcurrentHashMap分段锁优…

SwiftUI 4.0 中 List 显示层级数据的子视图在展开和收起操作时无动画的解决

问题现象 在 SwiftUI 4.0(iOS 16+)中,一个超简单 List 视图层级子视图的收放操作竟然没有动画,这着实有点让人不爽: 从上图可以看到:我们在点击 List 子项时不仅毫无收放动画可言,而且在展开时还有卡顿,显得非常生硬。 以上代码在目前最新的 iOS 16.4.1(a) 系统中测试…

非常提效的7款原型工具推荐

原型图工具允许在开发前进行测试和迭代过程&#xff0c;可以帮助节省大量的开发时间和成本。在本文中&#xff0c;我们盘点了7个易于使用的原型图工具&#xff0c;以提高您的生产力&#xff01; 1.即时设计 即时设计是一款免费的在线 UI 设计工具&#xff0c;无系统限制&…

Rust Atomics and Locks 阅读笔记 第二章 Atomics

原子操作&#xff08;atomic operations&#xff09;是多线程实现的基石&#xff0c;互斥锁&#xff08;mutex&#xff09;和条件变量&#xff08;condition variable&#xff09;都是通过原子操作来实现&#xff1b;std::sync::atomic包括了rust的内置原子操作类型&#xff08…

【C++入门编程常见问题】(小白必看)

常见问题 vsstudio快捷键 快速注释组合键 ctrlk ctrlc 取消注释快捷键 ctrlk ctrl u 支持垃圾回收机制 大多数面向对象编程语言具有垃圾回收机制。早期的C语言不具备垃圾回收机制&#xff0c;这意味着申请的内存资源在使用完成后&#xff0c;需要程序员自己释放。直到C11标…