关于Android Room 数据库的使用
一、介绍
Room 持久性库在SQlite的基础上提供了一个抽象成,让用户能够充分利用 SQLite 的强大功能的同时,获享强健的数据库访问机制。
二、理论知识
2.1 Room 有 3 个主要的组件:
- Database:包含数据库持有者,并作为与 App 持久关联数据的底层连接的主要访问点。
用 @Database 注解的类应满足以下条件: 1、是一个继承至 RoomDatabase 的抽象类。 2、 在注解中包含与数据库相关联的实体列表。 3、包含一个具有 0 个参数的抽象方法,并返回用 @Dao 注解的类。 在运行时,您可以通过调用 Room.databaseBuilder() 或 Room.inMemoryDatabaseBuilder() 获取 Database 实例。
-
Entity:表示数据库内的表(Table)。
-
DAO:包含用于访问数据库的方法。
2.2 Room 各组件间关系
Room 的大致使用方法如下:
- App 通过 Room 的 Database 获取与数据库相关的数据库访问对象(DAO)。
- 然后,App 使用 DAO 从数据库中获取 Entity,并且将 Entity 的变化保存到数据库中。
- 最后,APP 使用 Entity 获取和设置数据库中表的数据。
Room 中各组件之间的关系如图2- 1Room 架构图所示:
图 2- 1Room 架构图三、使用(Java版)
3.1 声明依赖项
如需添加 Room 的依赖项,您必须将 Google Maven 代码库添加到项目中。如需了解详情,请参阅 Google 的 Maven 代码库。
在应用或模块的 build.gradle
文件中添加所需工件的依赖项
dependencies {
def room_version = "2.3.0"
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"
}
3.2 一个实体类(Entry)
User
@Entity(tableName = "user")
public class User {
@PrimaryKey(autoGenerate = true) // 设置为主键自动增长
public int uid;
@ColumnInfo(name = "first_name")
public String firstName;
@ColumnInfo(name = "last_name")
public String lastName;
}
3.3 访问数据库的方法(Dao)
UserDao
@Dao
public interface UserDao {
@Query("SELECT * FROM user")
LiveData<List<User>> doFindAll();
@Query("SELECT * FROM user WHERE uid IN (:userIds)")
LiveData<List<User>> loadAllByIds(int[] userIds);
@Query("SELECT * FROM user WHERE first_name LIKE :first AND " +
"last_name LIKE :last LIMIT 1")
User doFindByName(String first, String last);
@Insert
void insert(User... users);
@Delete
void delete(User... user);
@Update
void update(User... user);
@Query("DELETE FROM user")
void delAllUser();
}
3.4 构建 RoomDatabase
AppDatabase
@Database(entities = {User.class,}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
private static final String DB_NAME = "jchat.db";
private static AppDatabase sAppDatabase;
public abstract UserDao userDao();
public static AppDatabase getInstance(Context context) {
if (sAppDatabase == null)
sAppDatabase = create(context);
return sAppDatabase;
}
private static AppDatabase create(Context context) {
return Room.databaseBuilder(context, AppDatabase.class, DB_NAME).build();
}
}
3.5android不建议在主线程中读写数据库,所以我们使用异步线程 AsyncTask 操作数据库,我们使用 Repository 和 ViewModel 的方式搭建数据库操作,如下:
3.5.1 AppRepository
public class AppRepository {
private AppDatabase mAppDatabase;
private LiveData<List<User>> mAllUsers;
private UserDao mUserDao;
public AppRepository(Context context) {
super();
mAppDatabase = AppDatabase.getInstance(context);
mUserDao = mAppDatabase.userDao();
mAllUsers = mUserDao.doFindAll();
}
public LiveData<List<User>> getAllUsers() {
return mAllUsers;
}
void insertUser(User... users) {
new InsertUserAsyncTask(mUserDao).execute(users);
}
void deleteUser(User... users) {
new DeleteUserAsyncTask(mUserDao).execute(users);
}
void updateUser(User... users) {
new UpdateUserAsyncTask(mUserDao).execute(users);
}
void deleteAllUser() {
new DelAllUserAsyncTask(mUserDao).execute();
}
void findUser(User user) {
new FindUserAsyncTask(mUserDao).execute(user);
}
void findAllUser() {
new FindAllUserAsyncTask(mUserDao).execute();
}
public void closeDataBase() {
if (mAppDatabase != null) {
if (mAppDatabase.isOpen()) {
mAppDatabase.close();
mAppDatabase = null;
}
}
}
//一个异步线程 三个参数 对象,进度,结果\
/**
* 插入数据
*/
static class InsertUserAsyncTask extends AsyncTask<User, Void, Void> {
private UserDao userDao;
InsertUserAsyncTask(UserDao userDao) {
this.userDao = userDao;
}
@Override
protected Void doInBackground(User... users) {
userDao.insert(users);
return null;
}
}
/**
* 删除数据
*/
static class DeleteUserAsyncTask extends AsyncTask<User, Void, Void> {
private UserDao userDao;
DeleteUserAsyncTask(UserDao userDao) {
this.userDao = userDao;
}
@Override
protected Void doInBackground(User... users) {
userDao.delete(users);
return null;
}
}
/**
* 更新数据
*/
static class UpdateUserAsyncTask extends AsyncTask<User, Void, Void> {
private UserDao userDao;
UpdateUserAsyncTask(UserDao userDao) {
this.userDao = userDao;
}
@Override
protected Void doInBackground(User... users) {
userDao.update(users);
return null;
}
}
/**
* 删除所有数据
*/
public static class DelAllUserAsyncTask extends AsyncTask<User, Void, Void> {
private UserDao userDao;
DelAllUserAsyncTask(UserDao userDao) {
this.userDao = userDao;
}
@Override
protected Void doInBackground(User... users) {
userDao.delAllUser();
return null;
}
}
/**
* 查找数据
*/
static class FindUserAsyncTask extends AsyncTask<User, Void, User> {
private UserDao userDao;
FindUserAsyncTask(UserDao userDao) {
this.userDao = userDao;
}
@Override
protected User doInBackground(User... users) {
return userDao.doFindByName(users[0].firstName, users[0].lastName);
}
}
/**
* 查找数据
*/
static class FindAllUserAsyncTask extends AsyncTask<User, Void, LiveData<List<User>>> {
private UserDao userDao;
FindAllUserAsyncTask(UserDao userDao) {
this.userDao = userDao;
}
@Override
protected LiveData<List<User>> doInBackground(User... users) {
return userDao.doFindAll();
}
}
}
3.5.2 AppViewModel
public class AppViewModel extends AndroidViewModel {
private AppRepository mRepository;
public AppViewModel(@NonNull Application application) {
super(application);
mRepository = new AppRepository(application);
}
public LiveData<List<User>> getAllUser() {
return mRepository.getAllUsers();
}
public void insertUser(User... users) {
mRepository.insertUser(users);
}
public void delUser(User... users) {
mRepository.deleteUser(users);
}
public void updateUser(User... users) {
mRepository.updateUser(users);
}
public void delAll() {
mRepository.deleteAllUser();
}
public void findUser(User user) {
mRepository.findUser(user);
}
public void findAllUser(){
mRepository.findAllUser();
}
public void closeDataBase() {
mRepository.closeDataBase();
}
}
3.6 实现MainActivity
3.6.1 界面 activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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="wrap_content"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:id="@+id/btn_add"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="插入数据" />
<Button
android:id="@+id/btn_del"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="删除数据" />
<Button
android:id="@+id/btn_update"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="更新数据" />
<Button
android:id="@+id/btn_select"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="查询数据" />
</LinearLayout>
3.6.2 MainActivity.java
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding mBinding;
private AppViewModel mAppViewModel;
private List<User> mUsers;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mBinding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(mBinding.getRoot());
init();
initListener();
}
private void init() {
mAppViewModel = new AppViewModel(getApplication());
mUsers = new ArrayList<>();
for (int i = 0; i < 10; i++) {
User user = new User();
user.firstName = "李00" + i;
user.lastName = "小明00" + i;
mUsers.add(user);
}
}
private void initListener() {
mBinding.btnAdd.setOnClickListener(v -> {
for (User item : mUsers) {
mAppViewModel.insertUser(item);
}
});
mBinding.btnDel.setOnClickListener(v -> {
User user = new User();
user.uid = 2;
mAppViewModel.delUser(user);
});
mBinding.btnUpdate.setOnClickListener(v -> {
User user = new User();
user.uid = 1;
user.firstName = "朱001";
mAppViewModel.updateUser(user);
});
mBinding.btnSelect.setOnClickListener(v -> {
mAppViewModel.findAllUser();
});
}
}
3.6.3 插入数据
3.6.4 删除数据
3.6.5 更新数据
3.6.7 操作后所有数据
3.7 最后,数据库可视化,可跳转至网页
3.7.1 依赖中添加
debugImplementation 'com.amitshekhar.android:debug-db:1.0.4'//数据库可视化,跳转至网页
3.7.2 在控制台中有打印的链接,然后跳转
D/DebugDB: Open http://192.168.1.31:8080 in your browser