AndroidはRoomを使用してローカル・データベースにデータを保存します
8612 ワード
RoomはSQLiteを上書きする抽象層を提供し、SQLiteのすべての機能を利用しながら、より便利でスムーズなデータベースアクセスを行うことができます.
依存の追加
自分のアプリケーションでRoomを使用するには、architectureコンポーネント依存性を追加する必要があります.
コンポーネント
Roomには3つの主要な部分があります. Database:データベースの所有者を含み、アプリケーションの永続関係データの基礎となる接続の主なアクセスポイントです.データベースを表すクラスは@Databaseコメントを使用します.このクラスは次の条件を満たす必要があります. は、RoomDatabaseに継承された抽象クラスです. @Databaseの注記で、データベースに関連付けられたエンティティのリストを宣言します. は、無参照の抽象メソッドを含み、DAO(@Dao注釈付きクラス)を返します.実行時には、
Entity:データベース内のテーブルを表し、一般的に@Entity注釈付きクラスです. DAO:データベースへのアクセス方法を含み、一般的に@Dao注釈付きインタフェースです.
サンプルコード
Entity:
DAO:
Database:
データベース・インスタンスの取得:
各RoomDatabaseのインスタンスのコストが大きいため、データベース・オブジェクトをインスタンス化する場合は、単一のパターンを使用することを推奨します.
内容の詳細
Entityのデフォルトでは、Roomはエンティティで定義された各フィールドに列を作成します.保存したくないフィールドがある場合は、変更フィールドに@Ignore注記を使用できます. Roomが正常にアクセスできるように、エンティティのフィールドをpublicに設定するか、getter/setterメソッドを提供します. プライマリ・キー:エンティティごとに少なくとも1つのフィールドをプライマリ・キーとして定義する必要があります.@PrimaryKey注記を使用します.RoomがエンティティにIDを自動的に割り当てる場合は、@PrimaryKey注記のautoGenerateプロパティをtrueに設定します.エンティティに複合プライマリ・キーがある場合は、@EntityのprimaryKeysプロパティを使用します. テーブル名:デフォルトでは、Roomはクラス名をデータベース・テーブル名として使用します.テーブルに異なる名前を付ける場合は、@EntityのtableNameプロパティを使用します.列名が同じである. 外部キー:Roomでは、エンティティ間で外部キー制約を定義できます. ネストされたオブジェクト:@Embedded注記を使用します.
DAOを使用したデータベースへのアクセス
注意データベースへのアクセスには、サブスレッドが必要です.
添削
Insertメソッドは、rowIdを返すデータを挿入します.deleteメソッドとupdateメソッドは、データベース内の入力パラメータのプライマリ・キーに一致するエントリをクエリーし、削除または更新操作を行い、削除または更新されたローの数を返すことができます.
調べる簡単なクエリー:
sql文クエリを直接使用し、複数のエントリを返す場合は配列で受信できます.参照クエリー: 部分列を調べる:
Roomクエリはfirst_を返しますnameとlast_name列の値で、NameTupleクラスのフィールドにマッピングできます.注記@Embedded注記も使用できます.パラメータのセット を渡す
また、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メソッドを実行し、正しい順序でデータベースをより高いバージョンに移行します.
参照リンク:https://developer.android.google.cn/training/data-storage/room/
依存の追加
自分のアプリケーションで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つの主要な部分があります.
Room.databaseBuilder()
またはRoom.inMemoryDatabaseBuilder()
を呼び出してインスタンスを取得できます.サンプルコード
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
@Entity(primaryKeys = {"account", "pos_curr", "offset", "type"})
public class User {
...
}
@Entity(tableName = "table_user", primaryKeys = {"account", "pos_curr", "offset", "type"})
public class User {
...
@ColumnInfo(name = "qr_xxx")
public String qr_str;//
}
@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;
}
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/