【Android】Room - SQLiteの代替

SQLite が Room に置き換えられたのはなぜですか?

なぜ SQLite が置き換えられるのでしょうか?

Sqlite2000年の誕生以来20年以上の歴史があり、この20年以上の間に初代Sqliteバージョン1.0から現在のバージョン3.0までバージョンアップしてきましたが、Androidがサポートする最新バージョン2.3.0でも、は引き続き Android で利用できますが、次のようないくつかの欠点がまだあります。

  • 生の SQL クエリのコンパイル時の検証はありません。
  • SQL クエリとデータ オブジェクトの間で変換するには、多くの定型コードが必要です。
  • これらの API は強力ですが、非常に低レベルであり、使用するには多大な時間と労力が必要です。

Sqlite一連の問題に対応して、 realm(iOS、Android に適用可能)、ObjectBox(クロスエンド、最速を主張する)、greenDaoその他のローカル データベースを置き換えることが目標でありSQLite、その後、公式でも新しいデータベースがリリースされました。 ---Room、これは完全に排除するんですかSqlite

答えは「いいえ」です。上記のデータベースは変更および最適化されていgreenDAO ます。の開発チームによって開発された製品です。Githubホームページでデータベースを皆さん推奨していますが、1 年以上更新されていません。おそらく、 Yes のピークは過ぎ、立ち上がるのが困難です。再びトップに戻ったので、徐々に使い始めているようで、将来に希望を失っています(個人的な推測です)。RoomSqliteObjectBoxgreenDAO greenDAOObjectBoxgreenDAOgreenDao

では、なぜ代わりに置き換えられるSQLiteのでしょうか? 個人的にはこれはひとえに公式の「公式発表」によるものだと思っています。Android Developers 公式 Web サイトの紹介ページや使用ガイドには、次のような文言があります。RoomgreenDaoSQLite

アプリの SQLite データベース内の情報にアクセスするための抽象化レイヤーとして Room Persistence Library を使用することを強くお勧めします

ここに画像の説明を挿入します
SQLite使用を諦める理由と説得する理由は、デメリットとメリットRoomです。SQLiteRoom

Roomアドバンテージ:

  • 簡素化されたデータベース移行パス。
  • SQL クエリのコンパイル時の検証。
  • 便利なコメントにより、重複やエラーが発生しやすい定型コードが最小限に抑えられます。

統合ルーム

Room には、次の 3 つの主要なコンポーネントが含まれています。

  • データベース: データベースを保持し、アプリケーションの永続データへの基礎となる接続のプライマリ アクセス ポイントとして機能するデータベース クラス。
  • エンティティ: アプリケーション データベース内のテーブルのデータ エンティティを表します。
  • Dao: アプリケーションがデータベース内のデータのクエリ、更新、挿入、削除に使用できるメソッドを提供するデータ アクセス オブジェクト。

依存関係をインポートする

implementation("androidx.room:room-runtime:2.4.2")
annotationProcessor("androidx.room:room-compiler:2.4.2")

// 使用 Kotlin 注释处理工具 (kapt)
kapt("androidx.room:room-compiler:2.4.2")

注: Kotlin プラグインは、Dagger や DBFlow などのアノテーション プロセッサをサポートしています。Kotlin クラスと連携するには、プラグインkaptを適用する必要がありますkotlin-kapt

apply plugin: 'kotlin-kapt'

クリックして最新バージョンの依存関係を表示します

Roomの利用にはDatabase、Entity、Daoの3つのステップがあり、それぞれの作成が完了した後でのみデータの書き込みや変更などが可能になります。

エンティティ(データエンティティ)

Room では、保存するオブジェクトを表すエンティティを定義できます。各エンティティは、関連付けられた Room データベース内のテーブルに対応し、エンティティの各インスタンスは、対応するテーブル内のデータの行を表します。

Kotlin バージョンの Entity は Java バージョンの Entity とは書き方が異なります。Java バージョンの Entity を記述する通常の方法は、新しいエンティティ クラスを作成し、変数の get メソッドと set メソッドを実装することです。Kotlin バージョンの Entity はキーワードを使用します. Kotlin では、マークされたクラスがdata class使用されますdata class. はデータ クラスであり、Kotlin のスーパー クラス,,Any詳細については、→ Kotlin データ クラス (データ)を参照してください。equals(other: Any?)hashCode()toString()

Room として宣言されたデータ クラスは、アノテーションdata classを使用して宣言する必要があります@Entity。デフォルトでは、Room はクラス名をデータベース テーブル名として使用します。クラス名をデータベース テーブル名と同じにしたくない場合は、パラメーターを設定できます@EntitytableName次のような注釈に@Entity(tableName = "自定义的数据库表名")パラメータを追加します。これ以降、このクラスによって生成されたデータベース テーブル名はクラス名ではなくなります。

@Entity
data class Classes(
    @PrimaryKey val classesId: String,
    @ColumnInfo val classesName: String
)

その他の注意事項

注釈 説明する
@PrimaryKey 対応するデータベーステーブルの各行を一意に識別するために使用されます。
@ColumnInfo データテーブルの列名を定義します。
@無視する データテーブルにフィールドを追加しないでください
@NonNull フィールドまたはメソッドの戻り値を null にすることはできません

@Entity詳しい使用方法については、「Room エンティティを使用したデータの定義」を参照してください。

Dao (データアクセスオブジェクト)

Dao: アプリケーションの残りの部分がデータ テーブル内のデータを操作するために使用するメソッドを提供します。

Dao はインターフェースクラスです。メソッド本体を記述する必要はありません。アノテーションを直接使用できます。追加、削除、変更、クエリは以下の 4 つのアノテーションに対応します。

注釈 説明する
@入れる 増加
@消去 消去
@アップデート 変化
@Query チェック

注釈は次のように使用されます。

@Dao
interface ClassesDao {
    
    
    /**
     * 增加多个班级
     */
    @Insert
    fun addMultipleClasses(vararg classes: Classes)
	/**
     * 删除某条数据
     */
    @Delete
    fun deleteClasses(classes: Classes)
    /**
     * 修改某条数据
     */
    @Update
    fun updateClasses(classes: Classes)
    /**
     * 查询classes表的数据
     */
    @Query("select * from classes")
    fun getAllClasses() : List<Classes>
}

Room では、値を含むクエリはコロンで表され、次のコードは、検索対象の className がインターフェイス呼び出し時に渡された値と等しいことを示します。

@Query("select * from classes where className = :classesName")
fun getAllClasses(classesName: String) : List<Classes>

Dao の詳しい使用方法については、「Room DAO を使用してデータにアクセスする」を参照してください。

データベース

Entity と Dao が定義されました。最後のステップは、データを保存するデータベース クラスを作成することです。作成されたクラスは、データベースの 3 つの条件を満たす必要があります。

  • クラスは、RoomDatabaseクラスを拡張する抽象クラスである必要があります。
  • データベースに関連付けられた Dao クラスごとに、データベース クラスはパラメーターを受け取らず、Dao クラスのインスタンスを返す抽象メソッドを定義する必要があります。
  • このクラスには、データベースに関連付けられたすべてのデータ エンティティ (データベースのバージョンを含む) をリストする配列を@Database含むアノテーションを付ける必要があります。entities
@Database(entities = [Classes::class/*数据库包含的实体*/], version = 1, exportSchema = false)
abstract class SchoolDatabase : RoomDatabase() {
    
    
    /**
     * 调用该方法获取Dao,来调用Classes表的接口方法
     */
    abstract fun classDao(): ClassesDao
}

使用

Room.databaseBuilder(applicationContext, SchoolDatabase::class.java, "数据库名称")
     .build()
     .classDao()
     .addClasses(classes)

効果

ここに画像の説明を挿入します

データ移行

データベースを移行する必要があるのはなぜですか?

ローカル データベースの開発中に、データベースのフィールドを変更した後、再起動時にクラッシュが発生するような問題が発生することがあります。

この問題に遭遇した学生の中には、「データベース フィールド変更クラッシュの解決策」のようなキーワードを使用して検索する場合があります。検索結果には、アプリをアンインストールして再インストールするように指示され、問題は解決されます。しかし、一見正しいように見えるこの方法は、実は致命的です。

ローカル データベースは一度変更され、パッケージ化されてリリースされます。ユーザーがアプリを更新した後にローカル データベースを使用すると、例外Room cannot verify the data integrity. Looks like you've changed schema but forgot to update the version number. You can simply fix this by increasing the version number.エラーが報告されます。

ここに画像の説明を挿入します
アプリのインターフェースが 8 秒以内に読み込まれない場合、ユーザーの 70% が失われます。これが 8 秒ルールです。では、アプリが一度クラッシュすると、何人のユーザーが失われるでしょうか? 上記の問題を解決するために、データベースのみを移行することができ、データ移行は自動移行と手動移行に分けられます。

自動移行

自動移行では、自動移行に対して次の 4 つのアノテーションが提供されます。

それの使い方:

// 版本更新前的数据库类.
@Database(
  version = 1,
  entities = [User::class]
)
abstract class AppDatabase : RoomDatabase() {
    
    
  ...
}

// 版本更新后的数据库类.
@Database(
  version = 2,
  entities = [User::class],
  exportSchema = true,
  autoMigrations = [
    AutoMigration (from = 1, to = 2)
  ]
)
abstract class AppDatabase : RoomDatabase() {
    
    
  ...
}

現在公式では自動移行用のアノテーションが上記の4つしか提供していないため、どのようにフィールドを追加するのかが謎となっていますが、この記事を見て自動移行用の新しいデータテーブルフィールドを知った方は、ぜひコメント欄にご参加いただければ幸いです. シェアする。

注:
1. 移行の失敗を避けるために、自動移行をexportSchema設定する必要がありますtrue
2. 自動移行は 2.4.0-alpha01 以降のバージョンにのみ適用できます。それより前のバージョンや複雑なアーキテクチャの変更を伴う状況の場合は、手動移行を使用する必要があります。

参考記事:ルームデータベースの移行

手動移行

手動データベース移行の最初のステップは、データ テーブル構造を変更することです。

@Entity
data class Classes(
    @PrimaryKey(autoGenerate = true) val classesId: Int = 0,
    @ColumnInfo(name = "className") var classesName: String,
    // 新增的列
    @ColumnInfo(name = "classesNum") var classesNum: String
)

手動移行に使用される方法は、新しいクラスを追加して移行を完了することRoomDatabase.Builderです。addMigrations(@NonNull Migration... migrations)Migration

Room の最下層では SQLite を使用します。データ移行では SQLiteexecSQL(String sql)メソッドを使用して SQL ステートメントを実行し、データベースを変更して移行を完了します。コードは次のとおりです:

var db: SchoolDatabase ?= null
// 单例模式的双重检查锁
fun getDataBase(context: Context) : SchoolDatabase{
    
    
    if (db == null){
    
    
        synchronized(SchoolDatabase::class.java){
    
    
            if (db == null){
    
    
                db = Room.databaseBuilder(context.applicationContext, SchoolDatabase::class.java, "school")
                    // .fallbackToDestructiveMigration()
                    // 添加数据迁移
                    .addMigrations(MIGRATION_1_TO_2)
                    .build()
            }
        }
    }
    return db as SchoolDatabase;
}

// Migration实例的两个参数指的是当前版本升级到什么版本
val MIGRATION_1_TO_2 : Migration = object : Migration(1, 2) {
    
    
    override fun migrate(database: SupportSQLiteDatabase) {
    
    
        //  添加新的列使用 底层SQLite + sql 语法,其它增删改查亦是如此
        database.execSQL("alter table classesNum add column 新增的列名 列名的数据类型 default 'null'")
    }
}

最後に、データベース クラス名の@Database注釈パラメータを最新バージョンにversion変更することを忘れずに、再度実行して移行を完了します。

参考:Android開発基本チュートリアル

RxJava で使用

Room がデータベース操作を実行するとき、デフォルトではサブスレッドが使用されます。メインスレッドで実行する必要がある場合は、それを呼び出してRoom のメインスレッドのクエリ チェックを無効にすることができます。ただし、この操作はクエリの実行速度が増加するため、お勧めできませんRoom.databaseBuilderallowMainThreadQueries()ANR がトリガーされる確率。

Room 操作を実行するたびに新しいインターフェースを作成しThreadて実装すればRunnable、ANR をトリガーするのが簡単になるのではないでしょうか?

この目的のために、公式はスレッド間の切り替えを容易にするために Rxjava と組み合わせて使用​​されるライブラリをリリースしました。

// optional - RxJava3 support for Room
implementation("androidx.room:room-rxjava3:2.4.2")
// RxJava3
implementation ("io.reactivex.rxjava3:rxjava:3.1.3")
implementation ("io.reactivex.rxjava3:rxandroid:3.0.0")

RxJavaと組み合わせた具体的な操作については、以下の記事を参照してください。
1.ルームデータベースの実践:RxJavaを使用した使用とカプセル化
2. RxJava2を使用したルーム、使用方法、経験と注意事項


この記事のコード: [Android] Room - SQLite 置き換えデモ

参考資料
1. Android Room コード例
2. Android Developers —— Room
3. Android Developers —— Room 利用ガイド
4. Android Developers —— Room エンティティを使用したデータの定義

おすすめ

転載: blog.csdn.net/baidu_41616022/article/details/125424197