如何使用Android Room在DAO类中正确获取表名

时间:2018-03-05 11:50:26

标签: android kotlin android-room

我想知道在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

我想将所有名字放在一个且只有一个地方。

3 个答案:

答案 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.
    // ...
}