如何使用 Android Room 在 DAO class 中正确获取 table 名称
How to properly get table name in DAO class using Android Room
我想知道在 Android 房间查询中使用 table 名称时如何避免硬编码。我在 Kotlin
开发,但老实说在这个问题上 Java 或 Kotlin 并不重要。
让我们看看这个简单的 classes:
DAO接口:
@Dao
interface UserDAO {
@Query("SELECT * FROM USER")
fun getAll(): List<User>
}
实体class:
@Entity(tableName = "USER")
class User {
}
可以看到table名字"USER"硬编码在UserDAO的@Query中。如何避免这种情况?如何引用@Entity参数tableName?
我想把所有的名字都放在一个地方。
您可以在任何 Util classes 中创建常量,并且可以在 Entity 和 Dao class 中引用该变量,如下所示:-
假设在 MainActivity 中有
companion object {
const val TABLE_NAME: String="Cheese"
}
实体class
@Entity(tableName = MainActivity.TABLE_NAME)
和道class将是
@Query("SELECT * FROM "+MainActivity.TABLE_NAME)
注意:- 这是避免硬编码命名的常用方法,您可以从实体 class 中获取 table 名称(需要探索):) .
目前,对于 Kotlin 和 Java,您可以依赖内置的 SQL 语法高亮显示。因此,当您键入查询内容时,Android Studio 会建议已定义的 table 名称。也许您以某种方式关闭了该功能?
Don't forget to inject Android Room SQL Language
总而言之,如果您希望远离硬编码的东西,为什么不定义一个属于 Entity class 的伴生对象?恕我直言,混合数据(层)和 Activity class 不是一个好的概念。数据不知道 activity 之类的东西(或任何 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>
}
你可以在 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.javatableclass中这样做
@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中,将接口更改为public抽象class并继承BaseDao。您在 BaseDao 中指定的所有标准方法都将被传递。
@Dao
public abstract class UserDAO extends BaseDao<UserDAO>
{
// Add additional methods here specific to this table.
// ...
}
我想知道在 Android 房间查询中使用 table 名称时如何避免硬编码。我在 Kotlin
开发,但老实说在这个问题上 Java 或 Kotlin 并不重要。
让我们看看这个简单的 classes:
DAO接口:
@Dao
interface UserDAO {
@Query("SELECT * FROM USER")
fun getAll(): List<User>
}
实体class:
@Entity(tableName = "USER")
class User {
}
可以看到table名字"USER"硬编码在UserDAO的@Query中。如何避免这种情况?如何引用@Entity参数tableName?
我想把所有的名字都放在一个地方。
您可以在任何 Util classes 中创建常量,并且可以在 Entity 和 Dao class 中引用该变量,如下所示:-
假设在 MainActivity 中有
companion object {
const val TABLE_NAME: String="Cheese"
}
实体class
@Entity(tableName = MainActivity.TABLE_NAME)
和道class将是
@Query("SELECT * FROM "+MainActivity.TABLE_NAME)
注意:- 这是避免硬编码命名的常用方法,您可以从实体 class 中获取 table 名称(需要探索):) .
目前,对于 Kotlin 和 Java,您可以依赖内置的 SQL 语法高亮显示。因此,当您键入查询内容时,Android Studio 会建议已定义的 table 名称。也许您以某种方式关闭了该功能? Don't forget to inject Android Room SQL Language
总而言之,如果您希望远离硬编码的东西,为什么不定义一个属于 Entity class 的伴生对象?恕我直言,混合数据(层)和 Activity class 不是一个好的概念。数据不知道 activity 之类的东西(或任何 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>
}
你可以在 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.javatableclass中这样做
@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中,将接口更改为public抽象class并继承BaseDao。您在 BaseDao 中指定的所有标准方法都将被传递。
@Dao
public abstract class UserDAO extends BaseDao<UserDAO>
{
// Add additional methods here specific to this table.
// ...
}