AndroidはRoomを使用してローカル・データベースにデータを保存します

8612 ワード

RoomはSQLiteを上書きする抽象層を提供し、SQLiteのすべての機能を利用しながら、より便利でスムーズなデータベースアクセスを行うことができます.
依存の追加
自分のアプリケーションでRoomを使用するには、architectureコンポーネント依存性を追加する必要があります.
dependencies {
    def room_version = "1.1.1"

    implementation "android.arch.persistence.room:runtime:$room_version"
    annotationProcessor "android.arch.persistence.room:compiler:$room_version"

    // optional - RxJava support for Room
    implementation "android.arch.persistence.room:rxjava2:$room_version"

    // optional - Guava support for Room, including Optional and ListenableFuture
    implementation "android.arch.persistence.room:guava:$room_version"

    // Test helpers
    testImplementation "android.arch.persistence.room:testing:$room_version"
}

コンポーネント
Roomには3つの主要な部分があります.
  • Database:データベースの所有者を含み、アプリケーションの永続関係データの基礎となる接続の主なアクセスポイントです.データベースを表すクラスは@Databaseコメントを使用します.このクラスは次の条件を満たす必要があります.
  • は、RoomDatabaseに継承された抽象クラスです.
  • @Databaseの注記で、データベースに関連付けられたエンティティのリストを宣言します.
  • は、無参照の抽象メソッドを含み、DAO(@Dao注釈付きクラス)を返します.実行時には、Room.databaseBuilder()またはRoom.inMemoryDatabaseBuilder()を呼び出してインスタンスを取得できます.

  • Entity:データベース内のテーブルを表し、一般的に@Entity注釈付きクラスです.
  • DAO:データベースへのアクセス方法を含み、一般的に@Dao注釈付きインタフェースです.

  • サンプルコード
    Entity:
    @Entity(primaryKeys = {"account", "pos_curr", "offset", "type"})
    public class User {
    
        @NonNull
        public String account = "";//  
    
        public int pos_curr;//  pos
    
        @ColumnInfo
        public int pos_end;//  pos
    
        @ColumnInfo
        public String qr_str;//     
    
        public int offset;//  
    
        @ColumnInfo
        public int multiple;//  
    
        public int type;//1:     2:  
        public String deviceId;//  id
    
    
        @Override
        public String toString() {
            return "User{" +
                    "account='" + account + '\'' +
                    ", pos_curr=" + pos_curr +
                    ", pos_end=" + pos_end +
                    ", qr_str='" + qr_str + '\'' +
                    ", offset=" + offset +
                    ", multiple=" + multiple +
                    ", type=" + type +
                    ", deviceId='" + deviceId + '\'' +
                    '}';
        }
    }
    

    DAO:
    @Dao
    public interface UserDao {
    
        @Insert(onConflict = OnConflictStrategy.REPLACE)
        long insertUser(User user);
    
        @Delete
        void delAll(User... users);
    
        @Query("SELECT * FROM User WHERE type = 1  ORDER BY pos_curr DESC,`offset` DESC LIMIT 1")
        User queryLastALi();
    
        @Query("SELECT * FROM User WHERE type = 2  ORDER BY pos_curr DESC,`offset` DESC LIMIT 1")
        User queryLastWeChat();
    }
    

    Database:
    @Database(entities = {User.class}, version = 1)
    public abstract class AppDatabase extends RoomDatabase {
        public abstract UserDao userDao();
    }
    

    データベース・インスタンスの取得:
    AppDatabase db = Room.databaseBuilder(getApplicationContext(),
            AppDatabase.class, "database-name").build();
    

    各RoomDatabaseのインスタンスのコストが大きいため、データベース・オブジェクトをインスタンス化する場合は、単一のパターンを使用することを推奨します.
    @Database(entities = {User.class}, version = 1, exportSchema = false)
    public abstract class AppDatabase extends RoomDatabase {
        private static AppDatabase INSTANCE;
        private static final Object sLock = new Object();
    
        public abstract UserDao userDao();
    
        public static AppDatabase getInstance(Context context) {
            synchronized (sLock) {
                if (INSTANCE == null) {
                    INSTANCE = Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, "user.db")
                                    .build();
                }
                return INSTANCE;
            }
        }
    }
    

    内容の詳細
    Entity
  • のデフォルトでは、Roomはエンティティで定義された各フィールドに列を作成します.保存したくないフィールドがある場合は、変更フィールドに@Ignore注記を使用できます.
  • Roomが正常にアクセスできるように、エンティティのフィールドをpublicに設定するか、getter/setterメソッドを提供します.
  • プライマリ・キー:エンティティごとに少なくとも1つのフィールドをプライマリ・キーとして定義する必要があります.@PrimaryKey注記を使用します.RoomがエンティティにIDを自動的に割り当てる場合は、@PrimaryKey注記のautoGenerateプロパティをtrueに設定します.エンティティに複合プライマリ・キーがある場合は、@EntityのprimaryKeysプロパティを使用します.
  • @Entity(primaryKeys = {"account", "pos_curr", "offset", "type"})
    public class User {
      ...
    }
    
  • テーブル名:デフォルトでは、Roomはクラス名をデータベース・テーブル名として使用します.テーブルに異なる名前を付ける場合は、@EntityのtableNameプロパティを使用します.列名が同じである.
  • @Entity(tableName = "table_user", primaryKeys = {"account", "pos_curr", "offset", "type"})
    public class User {
        ...
        @ColumnInfo(name = "qr_xxx")
        public String qr_str;//     
    }
    
  • 外部キー:Roomでは、エンティティ間で外部キー制約を定義できます.
  • @Entity(foreignKeys = @ForeignKey(entity = User.class,
            parentColumns = "id",
            childColumns = "user_id",
            onDelete = ForeignKey.CASCADE,
            onUpdate = ForeignKey.RESTRICT))
    public class Book {
        @PrimaryKey
        public int bookId;
    
        public String title;
    
        @ColumnInfo(name = "user_id")
        public int userId;
    }
    
    
    @Entity
    public class User {
        @PrimaryKey
        public int id;
    
        public String firstName;
        public String lastName;
    
        @Ignore
        Bitmap picture;
    }
    
  • ネストされたオブジェクト:@Embedded注記を使用します.
  • public class Address {
        public String street;
        public String state;
        public String city;
    
        @ColumnInfo(name = "post_code")
        public int postCode;
    }
    
    @Entity
    public class User {
        @PrimaryKey
        public int id;
    
        public String firstName;
    
        @Embedded
        public Address address;
    }
    

    DAOを使用したデータベースへのアクセス
    注意データベースへのアクセスには、サブスレッドが必要です.
    添削
    @Dao
    public interface UserDao {
    
        @Insert(onConflict = OnConflictStrategy.REPLACE)
        long insertUser(User user);
    
        @Delete
        void delAll(User... users);
        
        @Update
        void updateAll(User... users);
    }
    

    Insertメソッドは、rowIdを返すデータを挿入します.deleteメソッドとupdateメソッドは、データベース内の入力パラメータのプライマリ・キーに一致するエントリをクエリーし、削除または更新操作を行い、削除または更新されたローの数を返すことができます.
    調べる
  • 簡単なクエリー:
  • @Query("SELECT * FROM User WHERE type = 1  ORDER BY pos_curr DESC,`offset` DESC LIMIT 1")
    User queryLastALi();
    

    sql文クエリを直接使用し、複数のエントリを返す場合は配列で受信できます.
  • 参照クエリー:
  • @Query("SELECT * FROM user WHERE age BETWEEN :minAge AND :maxAge")
    User[] loadAllUsersBetweenAges(int minAge, int maxAge);
    
  • 部分列を調べる:
  • public class NameTuple {
        @ColumnInfo(name="first_name")
        public String firstName;
    
        @ColumnInfo(name="last_name")
        public String lastName;
    }
    
    @Dao
    public interface MyDao {
        @Query("SELECT first_name, last_name FROM user")
        public List loadFullName();
    }
    

    Roomクエリはfirst_を返しますnameとlast_name列の値で、NameTupleクラスのフィールドにマッピングできます.注記@Embedded注記も使用できます.
  • パラメータのセット
  • を渡す
        @Query("SELECT first_name, last_name FROM user WHERE region IN (:regions)")
        public List loadUsersFromRegions(List regions);
    

    また、LiveDataとRxJavaを組み合わせてObservableクエリーとReactiveクエリーを行うこともできますし、Cursorを直接返すこともできます.詳細は、「https://developer.android.google.cn/training/data-storage/room/accessing-data#query-observable
    データベースのアップグレード
    追加または変更機能を適用する場合、対応するテーブルを追加または変更する必要がある場合があります.単純にデータベース・バージョンをアップグレードすると、データベースが再構築され、以前のすべてのデータが失われることを意味します.Migrationを作成して古いバージョンのユーザーデータを保存することができ、各MigrationはstartVersionとendVersionを指定します.実行時、Roomは各Migrationのmigrateメソッドを実行し、正しい順序でデータベースをより高いバージョンに移行します.
    Room.databaseBuilder(getApplicationContext(), MyDb.class, "database-name")
            .addMigrations(MIGRATION_1_2, MIGRATION_2_3).build();
    
    static final Migration MIGRATION_1_2 = new Migration(1, 2) {
        @Override
        public void migrate(SupportSQLiteDatabase database) {
            database.execSQL("CREATE TABLE `Fruit` (`id` INTEGER, "
                    + "`name` TEXT, PRIMARY KEY(`id`))");
        }
    };
    
    static final Migration MIGRATION_2_3 = new Migration(2, 3) {
        @Override
        public void migrate(SupportSQLiteDatabase database) {
            database.execSQL("ALTER TABLE Book "
                    + " ADD COLUMN pub_year INTEGER");
        }
    };
    

    参照リンク:https://developer.android.google.cn/training/data-storage/room/