Android で使える ORM、Requery を試してみた
Android で使える ORM である Requery のセットアップとお試しです。
はじめに
Android の ORM は百花繚乱の様相を呈しており、それぞれ一長一短あるので選ぶのが難しいのですが、最近出てきた Requery が良さそうだったので、少し使ってみました。
ちなみに、Requery が良さそうに思えた点は以下のとおりです(重要度順):
- RxJava のサポートがしっかりしていそう
- マイグレーション機能
- ドキュメントが比較的揃っている
- Kotlin 用の機能
なお、ここで使った Requery のバージョンは 1.4.0 です。
また、サンプルコードは Kotlin です。
インストール
app/build.gradle
に以下の設定を入れます:
kapt { generateStubs = true // for Requery } def rxjava2_version = "2.1.3" def rxandroid_version = "2.0.1" def requery_version = "1.4.0" dependencies { ..... compile "io.reactivex.rxjava2:rxjava:$rxjava2_version" compile "io.reactivex.rxjava2:rxandroid:$rxandroid_version" compile "io.requery:requery:$requery_version" compile "io.requery:requery-android:$requery_version" compile "io.requery:requery-kotlin:$requery_version" kapt "io.requery:requery-processor:$requery_version" }
各バージョンは、現時点の最新版を指定しています。
初期化
初期化処理として、Application
の派生クラスに以下の設定を入れます:
class App : Application() { val DB_FILE_NAME = "app.db" val DB_VERSION = 1 val entityStore: KotlinReactiveEntityStore<Persistable> by lazy { val source = DatabaseSource(this, Models.DEFAULT, DB_FILE_NAME, DB_VERSION) source.setTableCreationMode(TableCreationMode.DROP_CREATE) // マイグレーション KotlinReactiveEntityStore<Persistable>(KotlinEntityDataStore(source.configuration)) } override fun onCreate() { .....
各パラメータは必要に応じて変更してください。
なお、Models
については、最初は参照エラーが発生します。
モデルを追加した後でビルドすると自動生成されるため、その後、参照を追加します。
モデルの定義
Requery の場合、モデルは抽象クラスかインターフェースで定義します。また、Kotlin の場合はデータクラスでも定義できます。
ここでは、抽象クラスで定義してみます:
@Entity @Table(name = "users") abstract class BaseUser { @Key @JvmField var id: Long = 0 @JvmField @Column(name = "display_name") var displayName: String = "" }
抽象クラスの名前は、接頭辞として Base
か Abstract
を付けます。そうすると、接頭辞のないクラスがサブクラスとして生成されます。
なお、現時点のバージョンでは、各カラム定義の前に @JvmField
を付けなければなりません。
これを付けないと、Entity field cannot be private
というエラーになります。
Ref.
- Defining Entities · requery/requery Wiki
- JPA (kapt) annotation processing generates duplicate attributes · Issue #571 · requery/requery
select
試しに Activity で select してみます:
class MainActivity : AppCompatActivity() { lateinit var entityStore: KotlinReactiveEntityStore<Persistable> val userNameView: TextView by bindView(R.id.userNameView) ..... override fun onCreate(savedInstanceState: Bundle?) { ..... entityStore = (application as App).entityStore showUserName() ..... } ..... fun showUserName() { val user = entityStore.select(User::class).get().firstOrNull() userNameView.text = user?.displayName ?: "(unknown)" } }
ここでは単純にするため、同期的に処理してみましたが、実アプリでは Rx で非同期的に処理した方が良いです。
Ref.
Rx
データ変更があったら自動的に select する処理を Rx で実装してみようとしたのですが、少しロジックを実装する必要があるようです:
How to observe table changes wothout select or count? · Issue #535 · requery/requery
Rx のサポートはまだ不十分かな。。。
ということで、Requery については、ここで一旦保留にしておきます。
エラー: クラスcom.example.app.models.Userが重複しています
いろいろ試行錯誤している途中で上記のようなエラーが発生しました。
その場合は、Android Studio の Build メニューから「Clean Project」すると解消しました。