关于Android Room 数据库的使用

300 阅读4分钟

关于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 架构图所示:

img

图 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 插入数据

image-20211207175808733

3.6.4 删除数据

image-20211207175848662

3.6.5 更新数据

image-20211207175942553

3.6.7 操作后所有数据

image-20211207180144557

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

END