記事ディレクトリ
1. Room フレームワークを使用する際のポイント
1. build.gradle ビルド スクリプトの構成手順
Room フレームワークの場合、Java言語とKotlin言語を使用した開発用にbuild.gradle ビルド スクリプトでさまざまな構成を行う必要があります。主に次の 2 つの構成があります。
- さまざまなプラグインが適用されます。
- 依存ライブラリをインポートするさまざまな方法。
アプリケーションプラグイン
適用されたプラグインの違い:
- Java 言語を使用して開発する場合は、Android プラグインをインポートするだけで済みます。
plugins {
id 'com.android.application'
}
- Kotlin 言語開発を使用する場合は、 Android プラグインに基づいて kotlin および kotlin-kapt プラグインを追加でインポートする必要があります。
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'kotlin-kapt'
}
依存関係をインポートする
依存ライブラリのインポートの違い:インポートが間違っている場合は、
- Java 言語開発を使用する場合は、 annotationProcessor を使用してアノテーション プロセッサをインポートし、コンパイル中にコードを生成する必要があります。
// 导入 Room 依赖库
implementation 'androidx.room:room-runtime:2.2.5'
// 导入注解处理器 ( Java )
annotationProcessor 'androidx.room:room-compiler:2.2.5'
- Kotlin 言語開発を使用する場合は、 kapt を使用してアノテーション プロセッサをインポートし、コンパイル中にコードを生成する必要があります。
// 导入 Room 依赖库
implementation 'androidx.room:room-runtime:2.2.5'
// 导入注解处理器 ( Kotlin )
kapt 'androidx.room:room-compiler:2.2.5'
2.Entityエンティティクラスを定義する
Roomフレームワークを使用したアプリケーションでは、 Entity エンティティ クラスがデータベーステーブルに対応します。Entity エンティティ クラスが定義されると、データベース定義されたことになります。
@Entity アノテーション
Entity エンティティ クラスは、 @Entity アノテーションを使用して変更する必要があります。このアノテーションは、データベース テーブルの名前を定義するために使用されるtableName パラメーターに渡すことができます。
@Entity(tableName = "student")
class Student {
}
@PrimaryKey アノテーション
主キーを定義し、@PrimaryKey アノテーションを使用して主キーを変更し、autoGenerate = true パラメーターを設定して主キーを自動インクリメントします。
データベース テーブルの列情報は @ColumnInfo アノテーションを使用して定義され、このアノテーションのパラメータは次のとおりです。
- name = "id" はデータテーブルの列名を定義します。
- typeAffinity = ColumnInfo.INTEGER は、列フィールドの型が int integer であることを定義します。
/**
* @PrimaryKey 设置主键 autoGenerate 为自增
* @ColumnInfo name 设置列名称 / typeAffinity 设置列类型
*/
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "id", typeAffinity = ColumnInfo.INTEGER)
var id: Int = 0
@ColumnInfo アノテーション
通常のフィールドを定義するには、アノテーションを使用してフィールドを変更するだけでよく、データベースのテーブル名を設定し、列の型を文字列型に設定します。@ColumnInfo
name = "name"
typeAffinity = ColumnInfo.TEXT
/**
* 姓名字段
* 数据库表中的列名为 name
* 数据库表中的类型为 TEXT 文本类型
*/
@ColumnInfo(name = "name", typeAffinity = ColumnInfo.TEXT)
lateinit var name: String
@注釈を無視する
変更されたフィールド
一部のフィールドをデータベース テーブルの列として設定する必要がない場合、それらはビジネス ロジックでのみ使用され、データベースに挿入する必要はなく、フィールドを変更するためにのみ使用されます。@Ignore
/**
* 有些属性用于做业务逻辑
* 不需要插入到数据库中
* 使用 @Ignore 注解修饰该属性字段
*/
@Ignore
lateinit var studentInfo: String
修飾子関数
@Ignore アノテーションを使用してコンストラクターをマークすると、Room フレームワークはコンストラクターを使用しなくなります。
次の 3 つのコンストラクターのうち、
- Room フレームワークは
constructor(id: Int, name: String, age: Int)
コンストラクターを使用します。 constructor(name: String, age: Int)
開発者はおよびconstructor(id: Int)
コンストラクターを使用します。
/**
* 默认的构造方法给 Room 框架使用
*/
constructor(id: Int, name: String, age: Int) {
this.id = id
this.name = name
this.age = age
}
/**
* 使用 @Ignore 注解标注构造函数后
* Room 就不会使用该构造方法了
* 这个构造方法是给开发者使用的
*/
@Ignore
constructor(name: String, age: Int) {
this.name = name
this.age = age
}
/**
* 使用 @Ignore 标签标注后
* Room 就不会使用该构造方法了
* 这个构造方法是给开发者使用的
*/
@Ignore
constructor(id: Int) {
this.id = id
}
3. Daoデータベースアクセスオブジェクトインターフェースを定義する
@Dao アノテーション
定義された Dao データベース アクセス オブジェクト インターフェイスは、 @Dao アノテーションで変更されたインターフェイス インターフェイスです。
/**
* 数据库访问对象接口 / 使用 @Dao 注解修饰
* 提供数据库的增删改查方法
*/
@Dao
interface StudentDao {
@注釈を挿入
データベースにデータを挿入するには、@Insert アノテーションを使用して、対応する抽象メソッドを変更します。
/**
* 向数据库表中插入元素
*/
@Insert
fun insert(student: Student)
@注釈を削除
データベースからデータを削除するには、@Delete アノテーションを使用して、対応する抽象メソッドを変更します。
/**
* 从数据库表中删除元素
*/
@Delete
fun delete(student: Student)
@Update アノテーション
データベース内のデータを更新するには、@Update アノテーションを使用して、対応する抽象メソッドを変更します。
/**
* 修改数据库表元素
*/
@Update
fun update(student: Student)
@Queryアノテーション
データベース内のデータをクエリするには、@Query アノテーションを使用して、対応する抽象メソッドを変更します。
文字列パラメータはクエリの SQL ステートメントである注釈に設定でき、受信パラメータにはコロンを使用してアクセスできます。:
/**
* 查询数据库表
*/
@Query("select * from student")
fun query(): List<Student>
/**
* 根据传入的 id 查询数据库表
* 在注解中使用 :id 调用参数中的 id: Int
*/
@Query("select * from student where id = :id")
fun query(id: Int): List<Student>
4. RoomDatabase データベース インスタンス クラスを定義します。
定義された RoomDatabase データベース インスタンス クラスは抽象クラスであり、RoomDatabase 抽象クラスを継承し、同時に@Database
アノテーション必要があります。
@Database(entities = [Student::class], version = 1, exportSchema = false)
abstract class StudentDatabase: RoomDatabase() {
この抽象クラスに抽象メソッドを定義して、データベース アクセス オブジェクトを取得します。
/**
* 获取 数据库访问 对象
* 这是必须要实现的函数
*/
abstract fun studentDao(): StudentDao
このクラスをシングルトン クラスとして設定し、シングルトン クラス オブジェクトの初期化時にデータベースを作成します。
companion object {
lateinit var instance: StudentDatabase
fun inst(context: Context): StudentDatabase {
if (!::instance.isInitialized) {
synchronized(StudentDatabase::class) {
// 创建数据库
instance = Room.databaseBuilder(
context.applicationContext,
StudentDatabase::class.java,
"student_database.db")
.allowMainThreadQueries() // Room 原则上不允许在主线程操作数据库
// 如果要在主线程操作数据库需要调用该函数
.build()
}
}
return instance;
}
}
データベースコードを初期化します。
- まず、 Room.databaseBuilder 関数を呼び出し、RoomDatabase.Builder オブジェクトを作成し、Context コンテキスト、StudentDatabase クラス オブジェクト、データベース名などのパラメーターを渡します。
- 次に、 RoomDatabase.Builder オブジェクトの build 関数を呼び出してデータベースを作成します。
- 注: 原則として、Room ではメイン スレッドでのデータベース操作は許可されていません。メイン スレッドでデータベースを操作したい場合は、 RoomDatabase.Builder # allowedMainThreadQueries 関数を呼び出してメイン スレッドの操作を許可する必要があります。
// 创建数据库
instance = Room.databaseBuilder(
context.applicationContext,
StudentDatabase::class.java,
"student_database.db")
.allowMainThreadQueries() // Room 原则上不允许在主线程操作数据库
// 如果要在主线程操作数据库需要调用该函数
.build()
5. Room フレームワークを呼び出してデータベースにアクセスします
まず、 RoomDatabase データベース インスタンス クラスを取得し、そのシングルトン取得関数を呼び出し、この関数を呼び出して対応するデータベースを作成します。
// 获取 StudentDatabase
var studentDatabase: StudentDatabase = StudentDatabase.inst(this)
次に、 データベース アクセス オブジェクト Dao を取得し、RoomDatabase データベース インスタンス クラスの抽象メソッドを通じて取得します。
// 获取数据库访问对象
var studentDao: StudentDao = studentDatabase.studentDao()
最後に、 Dao データベース アクセス オブジェクトを使用してデータベース アクセス操作を実行します。スレッドでデータベースにアクセスすることをお勧めします。
thread(start = true) {
// 插入数据
var s1 = Student("Tom", 18)
var s2 = Student("Jerry", 16)
studentDao.insert(s1)
studentDao.insert(s2)
// 查询数据
var students = studentDao.query()
Log.i("MainActivity", "数据库查询结果 ( 插入后首次查询 ) : " + students)
// 更新数据 , 将学生年龄都设置为 20
for (i in 0.. students.size - 1) {
students[i].age = 20
studentDao.update(students[i])
}
students = studentDao.query()
Log.i("MainActivity", "数据库查询结果 ( 修改后查询结果 ) : " + students)
// 删除数据
var s_delete = Student(1) // 删除的元素只需要传入 id 即可
studentDao.delete(s_delete)
students = studentDao.query()
Log.i("MainActivity", "数据库查询结果 ( 删除后查询结果 ) : " + students)
}
2. 完全なコード例
1. build.gradle ビルド スクリプト
build.gradle ビルド スクリプトでは、主に Kotlin プラグインと Kotlin アノテーション プラグインをインポートします。
Java 言語を使用して開発する場合は、これら 2 つのプラグインをインポートする必要はありません。
id 'org.jetbrains.kotlin.android'
id 'kotlin-kapt'
コンパイル時にコードを生成する Room 依存関係ライブラリとアノテーション プロセッサをインポートします。
// 导入 Room 依赖库
implementation 'androidx.room:room-runtime:2.2.5'
// 导入注解处理器 ( Kotlin )
kapt 'androidx.room:room-compiler:2.2.5'
// 导入注解处理器 ( Java )
//annotationProcessor 'androidx.room:room-compiler:2.2.5'
完全なコードは次のとおりです。
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'kotlin-kapt'
}
android {
namespace 'kim.hsl.roomdemo'
compileSdk 32
defaultConfig {
applicationId "kim.hsl.roomdemo"
minSdk 21
targetSdk 32
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
viewBinding {
// 启用 ViewBinding
enabled = true
}
}
dependencies {
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.5.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
// 导入 Room 依赖库
implementation 'androidx.room:room-runtime:2.2.5'
// 导入注解处理器 ( Kotlin )
kapt 'androidx.room:room-compiler:2.2.5'
// 导入注解处理器 ( Java )
//annotationProcessor 'androidx.room:room-compiler:2.2.5'
}
2. エンティティエンティティクラスコード
package kim.hsl.roomdemo
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.Ignore
import androidx.room.PrimaryKey
/**
* 定义数据库表 Entity 实体 / 同时定义数据库表 和 对鹰的实体类
* 设置该数据类对应数据库中的一张数据表, 表名为 student
* 该数据库表中的数据对应一个 Student 类实例对象
*/
@Entity(tableName = "student")
class Student {
/**
* @PrimaryKey 设置主键 autoGenerate 为自增
* @ColumnInfo name 设置列名称 / typeAffinity 设置列类型
*/
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "id", typeAffinity = ColumnInfo.INTEGER)
var id: Int = 0
/**
* 姓名字段
* 数据库表中的列名为 name
* 数据库表中的类型为 TEXT 文本类型
*/
@ColumnInfo(name = "name", typeAffinity = ColumnInfo.TEXT)
lateinit var name: String
/**
* 年龄字段
* 数据库表中的列名为 age
* 数据库表中的类型为 INTEGER 文本类型
*/
@ColumnInfo(name = "age", typeAffinity = ColumnInfo.INTEGER)
var age: Int = 0
/**
* 有些属性用于做业务逻辑
* 不需要插入到数据库中
* 使用 @Ignore 注解修饰该属性字段
*/
@Ignore
lateinit var studentInfo: String
/**
* 默认的构造方法给 Room 框架使用
*/
constructor(id: Int, name: String, age: Int) {
this.id = id
this.name = name
this.age = age
}
/**
* 使用 @Ignore 注解标注构造函数后
* Room 就不会使用该构造方法了
* 这个构造方法是给开发者使用的
*/
@Ignore
constructor(name: String, age: Int) {
this.name = name
this.age = age
}
/**
* 使用 @Ignore 标签标注后
* Room 就不会使用该构造方法了
* 这个构造方法是给开发者使用的
*/
@Ignore
constructor(id: Int) {
this.id = id
}
override fun toString(): String {
return "Student(id=$id, name='$name', age=$age)"
}
}
3. Daoデータベースアクセスオブジェクトインターフェースコード
@Dao アノテーションを使用してインターフェイス クラスを変更します。
@Insert 、 @Delete 、 @Update 、 @Queryアノテーション対応する追加、削除、変更、クエリ、およびその他の関数を変更します。
完全なコード:
package kim.hsl.roomdemo
import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query
import androidx.room.Update
/**
* 数据库访问对象接口 / 使用 @Dao 注解修饰
* 提供数据库的增删改查方法
*/
@Dao
interface StudentDao {
/**
* 向数据库表中插入元素
*/
@Insert
fun insert(student: Student)
/**
* 从数据库表中删除元素
*/
@Delete
fun delete(student: Student)
/**
* 修改数据库表元素
*/
@Update
fun update(student: Student)
/**
* 查询数据库表
*/
@Query("select * from student")
fun query(): List<Student>
/**
* 根据传入的 id 查询数据库表
* 在注解中使用 :id 调用参数中的 id: Int
*/
@Query("select * from student where id = :id")
fun query(id: Int): List<Student>
}
4. RoomDatabase データベース インスタンスのクラス コード
RoomDatabase データベース インスタンス クラスは、RoomDatabase 抽象クラスを継承し、@Database 注釈を使用して抽象クラスを変更する必要があります。
このうち、データベースアクセスオブジェクトを取得するための抽象関数を定義する。
このクラスをシングルトン クラスとして定義し、シングルトン オブジェクトの初期化時にデータベースを作成します。
完全なコード:
package kim.hsl.roomdemo
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
@Database(entities = [Student::class], version = 1, exportSchema = false)
abstract class StudentDatabase: RoomDatabase() {
/**
* 获取 数据库访问 对象
* 这是必须要实现的函数
*/
abstract fun studentDao(): StudentDao
companion object {
lateinit var instance: StudentDatabase
fun inst(context: Context): StudentDatabase {
if (!::instance.isInitialized) {
synchronized(StudentDatabase::class) {
// 创建数据库
instance = Room.databaseBuilder(
context.applicationContext,
StudentDatabase::class.java,
"student_database.db")
.allowMainThreadQueries() // Room 原则上不允许在主线程操作数据库
// 如果要在主线程操作数据库需要调用该函数
.build()
}
}
return instance;
}
}
}
5.アクティビティコンポーネントでRoomフレームワークを呼び出してデータベースにアクセスします。
まず、データベースインスタンス クラス StudentDatabase を取得します。
次に、データベースアクセス オブジェクト インターフェイス StudentDao を取得します。
最後に、 データベース アクセス オブジェクト インターフェイス StudentDao の一連のメソッドを呼び出してデータベースにアクセスします。
完全なコード:
package kim.hsl.roomdemo
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import kim.hsl.roomdemo.databinding.ActivityMainBinding
import kotlin.concurrent.thread
class MainActivity : AppCompatActivity() {
lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(getLayoutInflater())
setContentView(binding.root)
// 获取 StudentDatabase
var studentDatabase: StudentDatabase = StudentDatabase.inst(this)
// 获取数据库访问对象
var studentDao: StudentDao = studentDatabase.studentDao()
thread(start = true) {
// 插入数据
var s1 = Student("Tom", 18)
var s2 = Student("Jerry", 16)
studentDao.insert(s1)
studentDao.insert(s2)
// 查询数据
var students = studentDao.query()
Log.i("MainActivity", "数据库查询结果 ( 插入后首次查询 ) : " + students)
// 更新数据 , 将学生年龄都设置为 20
for (i in 0.. students.size - 1) {
students[i].age = 20
studentDao.update(students[i])
}
students = studentDao.query()
Log.i("MainActivity", "数据库查询结果 ( 修改后查询结果 ) : " + students)
// 删除数据
var s_delete = Student(1) // 删除的元素只需要传入 id 即可
studentDao.delete(s_delete)
students = studentDao.query()
Log.i("MainActivity", "数据库查询结果 ( 删除后查询结果 ) : " + students)
}
}
}