Existe-t-il un moyen de créer des DAO de classe de base génériques réutilisables avec Android Room?
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> { ... }
Je n'ai pas été en mesure de trouver un moyen d'y parvenir sans avoir à déclarer les mêmes membres d'interface et à écrire la requête pour chaque sous-classe. Lorsqu'il s'agit d'un grand nombre de DAO similaires, cela devient très fastidieux ...
Aujourd'hui, 08 août 2017, avec la version 1.0.0-alpha8 le Dao ci-dessous fonctionne. Je peux avoir d'autres Dao héros du GenericDao.
@Dao
public interface GenericDao<T> {
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insert(T... entity);
@Update
void update(T entity);
@Delete
void delete(T entity);
}
Cependant, GenericDao ne peut pas être inclus dans ma classe Database
J'ai une solution pour findAll.
Codes dans ce 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);
et d'autres Dao ressemblent à:
@Dao
public abstract class UserDao extends AppDao<User> {
}
C'est tout
L'idée est
Si vous préférez l'interface à la classe abstraite, vous pouvez essayer la méthode facultative Java 8.
Ce n'est pas beau mais a fonctionné, comme vous pouvez le voir.
AFAIK, vous ne pouvez le faire que pour insert()
, update()
et delete()
, car il ne nécessite pas d'instruction SQL spécifique qui doit être vérifiée au moment de la compilation .
exemple:
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();
}
Fonction findAll générique:
référentiel de base et 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>
}
service de base de données:
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
}
}
}
exemple repo et dao:
class UserRepository : BaseRepository<User>(User::class.Java) {
override val dao: UserDao
get() = database.userDao
}
@Dao
interface UserDao : BaseDao<User>