pqv*_*vst 22 android android-room android-architecture-components
有没有办法用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> { ... }
Run Code Online (Sandbox Code Playgroud)
我无法找到任何方法来实现这一点,而无需声明相同的接口成员并为每个子类编写查询.在处理大量类似的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);
}
Run Code Online (Sandbox Code Playgroud)
但是,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);
Run Code Online (Sandbox Code Playgroud)
和其他 Dao 看起来像:
@Dao
public abstract class UserDao extends AppDao<User> {
}
Run Code Online (Sandbox Code Playgroud)
就这样
这个想法是
如果你更喜欢接口而不是抽象类,你可以尝试 java 8 的可选方法。
正如你所看到的,它并不漂亮但有效。
通用的 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>
}
Run Code Online (Sandbox Code Playgroud)
数据库服务:
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
}
}
}
Run Code Online (Sandbox Code Playgroud)
示例 repo 和 dao:
class UserRepository : BaseRepository<User>(User::class.java) {
override val dao: UserDao
get() = database.userDao
}
@Dao
interface UserDao : BaseDao<User>
Run Code Online (Sandbox Code Playgroud)
虽然我同意你的想法,但答案是否定的。有几个原因。
当fooDao_Impl.java从您的类生成 时@Dao fooDao extends BaseDao<Foo>,您将遇到很多“找不到类符号 T”错误。这是由于 Room 用于生成 dao 实现的方法所致。这种方法不会支持您想要的结果,并且不太可能很快改变(在我看来,由于类型擦除)。
即使这个问题得到解决,Room 也不支持动态@Dao查询,以防止 SQL 注入。这意味着您只能动态地将值插入到查询中,而不能动态地将列名、表名或查询命令插入到查询中。在您的示例中,您不能使用,#{T}因为它会违反此原则。理论上,如果第 1 点中详述的问题得到解决,您可以用户插入、删除和更新。
| 归档时间: |
|
| 查看次数: |
6933 次 |
| 最近记录: |