web-dev-qa-db-ja.com

Android Roomを使用した再利用可能な汎用基本クラスDAO

Android Room?で再利用可能な汎用基本クラスDAOを作成する方法はありますか?

public interface BaseDao<T> {

  @Insert
  void insert(T object);

  @Update
  void update(T object);

  @Query("SELECT * FROM #{T} WHERE id = :id")
  void findAll(int id);

  @Delete
  void delete(T object);

}

public interface FooDao extends BaseDao<FooObject> { ... }

public interface BarDao extends BaseDao<BarEntity> { ... }

同じインターフェイスメンバを宣言し、各サブクラスのクエリを記述することなく、これを達成する方法を見つけることができませんでした。多数の同様のDAOを扱う場合、これは非常に退屈になります...

20
pqvst

今日、2017年8月8日、バージョン1.0.0-alpha8以下のDaoが機能します。他のDaoにGenericDaoをヒーローにすることができます。

@Dao
public interface GenericDao<T> {
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    void insert(T... entity);

    @Update
    void update(T entity);

    @Delete
    void delete(T entity);
}

ただし、GenericDaoをDatabaseクラスに含めることはできません

9
Natan

FindAllのソリューションがあります。

そのBaseDaoのコード:

...
public List<T> findAll() {
    SimpleSQLiteQuery query = new SimpleSQLiteQuery(
        "select * from " + getTableName()
    );
    return doFindAll(query);
}
...
public String getTableName() {
    // Below is based on your inheritance chain
    Class clazz = (Class)
        ((ParameterizedType) getClass().getSuperclass().getGenericSuperclass())
            .getActualTypeArguments()[0];
    // tableName = StringUtil.toSnakeCase(clazz.getSimpleName());
    String tableName = clazz.getSimpleName();
    return tableName;
}
...
@RawQuery
protected abstract List<T> doFindAll(SupportSQLiteQuery query);

その他のDaoは次のようになります。

@Dao
public abstract class UserDao extends AppDao<User> {
}

それで全部です

アイデアは

  1. 実行時にサブクラスのジェネリック型のテーブル名を取得します
  2. そのテーブル名をRawQueryに渡します

抽象クラスよりもインターフェイスを好む場合は、Java 8。

美しくはありませんが、機能していることがわかります。

ここで要点を作成しました

4
Clxy

知る限り、コンパイル時に検証する必要のある特定のSQLステートメントを必要としないため、insert()update()、およびdelete()に対してのみ実行できます。 。

例:

BaseDao.Java

public interface BaseDao<T> {

    @Insert
    void insert(T obj);

    @Insert
    void insert(T... obj);

    @Update
    void update(T obj);

    @Delete
    void delete(T obj);
}

UserDao.Java

@Dao
abstract class UserDao implements BaseDao<User> {

    @Query("SELECT * FROM User")
    abstract List<User> getUser();

}

ソース

1
Kharda

汎用findAll関数:

ベースリポジトリとdao:

abstract class BaseRepository<T>(private val entityClass: Class<T>) {

    abstract val dao: BaseDao<T>

    fun findAll(): List<T> {
        return dao.findAll(SimpleSQLiteQuery("SELECT * FROM ${DatabaseService.getTableName(entityClass)}"))
    }
}

interface BaseDao<T> {

    @RawQuery
    fun findAll(query: SupportSQLiteQuery): List<T>
}

データベースサービス:

object DatabaseService {

    fun getEntityClass(tableName: String): Class<*>? {
        return when (tableName) {
            "SomeTableThatDoesntMatchClassName" -> MyClass::class.Java
            else -> Class.forName(tableName)
        }
    }

    fun getTableName(entityClass: Class<*>): String? {
        return when (entityClass) {
            MyClass::class.Java -> "SomeTableThatDoesntMatchClassName"
            else -> entityClass.simpleName
        }
    }
}

リポジトリとdaoの例:

class UserRepository : BaseRepository<User>(User::class.Java) {

    override val dao: UserDao
        get() = database.userDao

}

@Dao
interface UserDao : BaseDao<User>
0
jc12