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を扱う場合、これは非常に退屈になります...
今日、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クラスに含めることはできません
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> {
}
それで全部です
アイデアは
抽象クラスよりもインターフェイスを好む場合は、Java 8。
美しくはありませんが、機能していることがわかります。
知る限り、コンパイル時に検証する必要のある特定の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();
}
汎用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>