【Android】Room数据库的基本使用
【Android】Room数据库的基本使用
一、什么是Room
🍔1.1 Room简介
Room是Android Jetpack组件库中的一部分,对SQLite进行了封装,简化了对SQLite数据库的操作,让开发者使用面向对象的方式(通过Java/Kotlin)来操作SQLite数据库,从而避免了编写大量繁琐的SQL代码和解析数据。
🌭1.2 三大核心组件
- Entity(实体类):用于表示数据库表的数据结构。
- DAO(Data Access Object):用于定义数据库操作的方法。
- Database(数据库类):用于创建数据库实例,并将 Entity 和 DAO 关联起来
二、使用步骤
🍿2.1 添加依赖
在app下的build.gradle下添加:
// app/build.gradle
dependencies {implementation "androidx.room:room-runtime:2.6.1"annotationProcessor "androidx.room:room-compiler:2.6.1"
}
🍕2.2 创建实体类 (Entity)
创建一个表示数据库表的 Java 类:
@Entity(tableName = "user-room")
public class MyUser {@PrimaryKey(autoGenerate = true)private int id;@ColumnInfo(name = "user_age")private int age;@ColumnInfo(name = "user_name")private String name;@ColumnInfo(name = "user_email")private String email;// 构造函数public MyUser(int age, String name, String email) {this.age = age;this.name = name;this.email = email;}// Getter 和 Setter 方法public int getId() { return id; }public void setId(int id) { this.id = id; }public int getAge() { return age; }public void setAge(int age) { this.age = age; }public String getName() { return name; }public void setName(String name) { this.name = name; }public String getEmail() { return email; }public void setEmail(String email) { this.email = email; }
}
- 各注解作用:
@Entity(tableName = "user-room")
:标记这是一个数据库表,同时指定表名@PrimaryKey(autoGenerate = true)
:设置主键并启用自动生成@ColumnInfo(name = "user_age")
:设置列名
🌮2.3 创建数据访问对象(DAO)
创建一个接口定义数据库操作:
@Dao
public interface MyUserDao {// 插入用户@Insertvoid insertUser(MyUser user);// 更新用户(通过对象)@Updateint updateUser(MyUser user);// 更新用户(通过名称,将age更新为传入的值)@Query("UPDATE `user-room` SET user_age = :age WHERE user_name = :name")int updateUser(String name, int age);// 查询所有用户@Query("SELECT * FROM `user-room`")List<MyUser> getAllUsers();// 查询特定用户(通过名称)@Query("SELECT * FROM `user-room` WHERE user_name = :name")List<MyUser> getUserByName(String name);// 删除用户(通过对象)@Deleteint deleteUser(MyUser user);// 删除用户(通过名称)@Query("DELETE FROM `user-room` WHERE user_name = :name")int deleteUserByName(String name);
}
- 各注解作用:
@Dao
:标记这是一个数据访问对象接口@Insert
、@Update
、@Delete
:由Room 提供的便捷注解,可以自动生成对应 SQL@Query
:自定义 SQL 查询,:参数名
表示方法参数
🏍️2.4 创建数据库类
创建一个抽象类用于扩展 RoomDatabase:
@Database(entities = {MyUser.class}, version = 1)
public abstract class MyUserDatabase extends RoomDatabase {public abstract MyUserDao userDao();// 数据库迁移(版本1到2)static final Migration MIGRATION_1_2 = new Migration(1, 2) {@Overridepublic void migrate(@NonNull SupportSQLiteDatabase database) {// 添加新列user_emaildatabase.execSQL("ALTER TABLE `user-room` ADD COLUMN user_email TEXT");}};
}
- 各注解作用:
@Database(entities = {MyUser.class}, version = 1)
:标记数据库类,指定包含的表和版本号Migration
:定义数据库版本迁移逻辑
关于数据库迁移:
-
数据库迁移的核心作用是在修改数据库结构后(比如在实体类中添加新字段或是在库中添加新表),安全、无损地将旧版本数据库升级到新版本,同时保留用户的原有数据。
-
版本迁移逻辑:必须增加数据库的版本号,并提供一个Migration对象来告诉Room如何从旧版本正确迁移到新版本。
💥2.5 在Activity中使用数据库
在Activity中初始化数据库并执行操作:
public class MainActivity extends AppCompatActivity {private MyUserDatabase userDatabase;private EditText nameEditText, ageEditText, emailEditText;private TextView resultTextView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 初始化视图nameEditText = findViewById(R.id.et_name);ageEditText = findViewById(R.id.et_age);emailEditText = findViewById(R.id.et_email);resultTextView = findViewById(R.id.tv_result);// 初始化数据库userDatabase = Room.databaseBuilder(getApplicationContext(),MyUserDatabase.class, "user-database.db").addMigrations(MyUserDatabase.MIGRATION_1_2) // 添加迁移规则.build();// 设置按钮点击事件findViewById(R.id.btn_insert).setOnClickListener(v -> insertUser());findViewById(R.id.btn_query).setOnClickListener(v -> queryUsers());findViewById(R.id.btn_update).setOnClickListener(v -> updateUser());findViewById(R.id.btn_delete).setOnClickListener(v -> deleteUser());}// 插入用户private void insertUser() {new Thread(() -> {try {String name = nameEditText.getText().toString();int age = Integer.parseInt(ageEditText.getText().toString());String email = emailEditText.getText().toString();MyUser user = new MyUser(age, name, email);userDatabase.userDao().insertUser(user);runOnUiThread(() -> Toast.makeText(MainActivity.this, "用户添加成功", Toast.LENGTH_SHORT).show());} catch (Exception e) {e.printStackTrace();}}).start();}// 查询用户private void queryUsers() {new Thread(() -> {List<MyUser> users = userDatabase.userDao().getAllUsers();StringBuilder result = new StringBuilder("所有用户:\n");for (MyUser user : users) {result.append("ID: ").append(user.getId()).append(", 姓名: ").append(user.getName()).append(", 年龄: ").append(user.getAge()).append(", 邮箱: ").append(user.getEmail()).append("\n");}runOnUiThread(() -> resultTextView.setText(result.toString()));}).start();}// 更新用户private void updateUser() {new Thread(() -> {try {String name = nameEditText.getText().toString();int age = Integer.parseInt(ageEditText.getText().toString());int updatedRows = userDatabase.userDao().updateUser(name, age);runOnUiThread(() -> Toast.makeText(MainActivity.this, "更新了 " + updatedRows + " 行数据", Toast.LENGTH_SHORT).show());} catch (Exception e) {e.printStackTrace();}}).start();}// 删除用户private void deleteUser() {new Thread(() -> {try {String name = nameEditText.getText().toString();int deletedRows = userDatabase.userDao().deleteUserByName(name);runOnUiThread(() -> Toast.makeText(MainActivity.this, "删除了 " + deletedRows + " 行数据", Toast.LENGTH_SHORT).show());} catch (Exception e) {e.printStackTrace();}}).start();}@Overrideprotected void onDestroy() {super.onDestroy();if (userDatabase != null && userDatabase.isOpen()) {userDatabase.close();}}
}
2.5.1 创建数据库
// 初始化数据库userDatabase = Room.databaseBuilder(getApplicationContext(),MyUserDatabase.class, "user-database.db").addMigrations(MyUserDatabase.MIGRATION_1_2) // 添加迁移规则.build();
- 参数一:上下文
- 参数二:数据库的class对象
- 参数三:表示要创建的 SQLite 数据库文件的名称。
2.5.1 增
// 插入用户@Insertvoid insertUser(MyUser user);
// 插入用户private void insertUser() {new Thread(() -> {try {String name = nameEditText.getText().toString();int age = Integer.parseInt(ageEditText.getText().toString());String email = emailEditText.getText().toString();MyUser user = new MyUser(age, name, email);userDatabase.userDao().insertUser(user);runOnUiThread(() -> Toast.makeText(MainActivity.this, "用户添加成功", Toast.LENGTH_SHORT).show());} catch (Exception e) {e.printStackTrace();}}).start();}
主要要在非主线程中进行,数据库操作是一个非常耗时的操作,在主线程进行可能会引起卡顿和崩溃,不过在Room操作中可以不用新开线程,因为它内部已经帮我们处理好了
2.5.2 删
// 删除用户(通过对象)@Deleteint deleteUser(MyUser user);// 删除用户(通过名称)@Query("DELETE FROM `user-room` WHERE user_name = :name")int deleteUserByName(String name);
// 删除用户private void deleteUser() {new Thread(() -> {try {String name = nameEditText.getText().toString();int deletedRows = userDatabase.userDao().deleteUserByName(name);runOnUiThread(() -> Toast.makeText(MainActivity.this, "删除了 " + deletedRows + " 行数据", Toast.LENGTH_SHORT).show());} catch (Exception e) {e.printStackTrace();}}).start();}
2.5.3 查
// 查询所有用户@Query("SELECT * FROM `user-room`")List<MyUser> getAllUsers();
// 查询用户private void queryUsers() {new Thread(() -> {List<MyUser> users = userDatabase.userDao().getAllUsers();StringBuilder result = new StringBuilder("所有用户:\n");for (MyUser user : users) {result.append("ID: ").append(user.getId()).append(", 姓名: ").append(user.getName()).append(", 年龄: ").append(user.getAge()).append(", 邮箱: ").append(user.getEmail()).append("\n");}runOnUiThread(() -> resultTextView.setText(result.toString()));}).start();}
2.5.4 改
// 更新用户(通过对象)@Updateint updateUser(MyUser user);// 更新用户(通过名称,将age更新为传入的值)@Query("UPDATE `user-room` SET user_age = :age WHERE user_name = :name")int updateUser(String name, int age);
// 更新用户private void updateUser() {new Thread(() -> {try {String name = nameEditText.getText().toString();int age = Integer.parseInt(ageEditText.getText().toString());int updatedRows = userDatabase.userDao().updateUser(name, age);runOnUiThread(() -> Toast.makeText(MainActivity.this, "更新了 " + updatedRows + " 行数据", Toast.LENGTH_SHORT).show());} catch (Exception e) {e.printStackTrace();}}).start();}
🎍2.6 布局文件(activity_main)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:padding="16dp"><EditTextandroid:id="@+id/et_name"android:layout_width="match_parent"android:layout_height="wrap_content"android:hint="输入姓名"/><EditTextandroid:id="@+id/et_age"android:layout_width="match_parent"android:layout_height="wrap_content"android:hint="输入年龄"android:inputType="number"/><EditTextandroid:id="@+id/et_email"android:layout_width="match_parent"android:layout_height="wrap_content"android:hint="输入邮箱"android:inputType="textEmailAddress"/><Buttonandroid:id="@+id/btn_insert"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="添加用户"/><Buttonandroid:id="@+id/btn_query"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="查询所有用户"/><Buttonandroid:id="@+id/btn_update"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="更新用户"/><Buttonandroid:id="@+id/btn_delete"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="删除用户"/><TextViewandroid:id="@+id/tv_result"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="16dp"/>
</LinearLayout>