我想知道在Android Room查询中使用表名时如何避免硬编码。我在Kotlin
开发,但说实话,这个问题无关紧要是Java或Kotlin。
让我们看看简单的类:
DAO界面:
@Dao
interface UserDAO {
@Query("SELECT * FROM USER")
fun getAll(): List<User>
}
实体类:
@Entity(tableName = "USER")
class User {
}
您可以看到表名“USER”在UserDAO中的@Query中进行了硬编码。怎么避免呢?如何引用@Entity参数 tableName ?
我想将所有名字放在一个且只有一个地方。
答案 0 :(得分:2)
你可以在任何Util类中创建一个常量,并且可以在Entity和Dao类中引用该变量,如下所示: -
假设你有MainActivity
companion object {
const val TABLE_NAME: String="Cheese"
}
实体类
@Entity(tableName = MainActivity.TABLE_NAME)
和 Dao类将是
@Query("SELECT * FROM "+MainActivity.TABLE_NAME)
注意: - 这是避免硬编码命名的常用方法,可能是您可以从实体类获取表名(需要探索):)。
答案 1 :(得分:0)
当前,对于Kotlin和Java而言,您都可以依靠内置的SQL语法高亮显示。结果,当您键入查询的内容时,Android Studio会建议已定义的表名。也许您已经以某种方式关闭了该功能? Don't forget to inject Android Room SQL Language
总而言之,如果您希望保留硬编码的内容,为什么不定义属于 Entity 类的伴随对象?恕我直言,混合数据(层)和活动类不是一个好主意。数据不知道诸如活动(或任何与UI相关的东西)之类的东西。拥有 Utils 听起来像是对所有内容都存在错误,而不是从关注的角度出发。
也许以下代码可以满足您的要求:
@Entity(tableName = WordPl.TABLE_NAME)
data class WordPl(var id: Int,
var word: String) {
companion object {
const val TABLE_NAME = "word_pl"
}
}
然后在您的DAO中,您可以使用Kotlin字符串模板:
@Dao
interface DictionaryDao {
@Query("Select * from ${WordPl.TABLE_NAME}")
fun getAllWords(): List<WordPl>
}
答案 2 :(得分:0)
你可以在 Java 中做这样的事情:
创建TableAnnotation.java接口文件
/**
* This annotation class is needed to obtain information about the table from the class at runtime.
* Needed passing the BaseDao needs to retrieve the table name from the parent class.
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface TableAnnotation {
String tableName();
}
在您的 User.java 表类中执行此操作
@TableAnnotation(tableName = User.tableName)
@Entity(tableName = User.tableName)
class User {
protected static final String tableName = "USER";
}
如果你想减少样板代码的数量,你可以在 BaseDao 中集成获取 tableName。 在你的 BaseDao.java 中你可以这样做
@Dao
public abstract class BaseDao<T> {
/**
* Get all objects from the database
* @return the table objects for the entries
*/
public List<T> getAllObjects() {
SimpleSQLiteQuery query = new SimpleSQLiteQuery(
"select * from " + getTableName() + " order by id"
);
return doGetAllObjectsById_(query);
}
@RawQuery
protected abstract List<T> doGetAllObjectsById_(SupportSQLiteQuery query);
/**
* Get an object from the database by id
* @param id
* @return the table object for the entry
*/
public T getObjectById(long id) {
SimpleSQLiteQuery query = new SimpleSQLiteQuery(
"select * from " + getTableName() + " where id = ?",
new Object[]{id}
);
return doGetObjectById_(query);
}
@RawQuery
protected abstract T doGetObjectById_(SupportSQLiteQuery query);
/**
* Get the table name of the parent class.
* @return
*/
private String getTableName() {
Class clazz = (Class)
((ParameterizedType) getClass().getSuperclass().getGenericSuperclass())
.getActualTypeArguments()[0];
TableAnnotation tableAnnotation = (TableAnnotation) clazz.getAnnotation(TableAnnotation.class);
String tableName = tableAnnotation.tableName();
return tableName;
}
}
在您的 UserDAO.java 中,将接口更改为公共抽象类并继承 BaseDao。您在 BaseDao 中指定的所有标准方法都将被传递。
@Dao
public abstract class UserDAO extends BaseDao<UserDAO>
{
// Add additional methods here specific to this table.
// ...
}