Android Room增删改查详解、报错的改正记录

一 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查询的时候,参数传的实体类,实体类不能转化成数据库里的列!

改正:

猜你喜欢

转载自blog.csdn.net/m0_45877477/article/details/125221618