在房间 android 的列上使用忽略
Using ignore on column in Room android
我的数据库 table 是
@Entity
internal data class ConversationEntity(
@PrimaryKey val conversationId: String,
val status: String,
val createdAt: String,
val modifiedAt: String,
val lastMessage: String? = null,
val feedbackType: ChatFeedbackType? = null
)
我想在 lastMessage
上使用 @Ignore
,但出现以下错误。
@Entity
internal data class ConversationEntity(
@PrimaryKey val conversationId: String,
val status: String,
val createdAt: String,
val modifiedAt: String,
@Ignore
val lastMessage: String? = null,
val feedbackType: ChatFeedbackType? = null)
我得到的错误
Entities and POJOs must have a usable public constructor. You can have an empty constructor or a constructor whose parameters match the fields (by name and type).
这里有什么问题?
我的道是
@Insert(onConflict = OnConflictStrategy.REPLACE)
abstract suspend fun saveConversations(entities: List<ConversationEntity>)
我目前的数据库版本是6。我是否还需要编写迁移查询来添加忽略?
将这个class用于实体
class ConversationEntity (){
@PrimaryKey
val conversationId: String
val status: String
val createdAt: String
val modifiedAt: String
@Ignore
val lastMessage: String? = null
val feedbackType: ChatFeedbackType? = null
}
当使用 @Ignore 时,@Ignore 不包含在 table 中,因此 Room 需要一个可用于 inserting/extracting 行的构造函数,而不是完整的默认构造函数。
因此您需要添加一个不包含 lastMessage
的 suitable 构造函数
我相信,在解决构造函数问题后,您会遇到一个问题,因为 Conversation 不是 public。您可以通过删除 internal 关键字来解决此问题。
例如
@Entity
data class ConversationEntity(
@PrimaryKey val conversationId: String,
val status: String,
val createdAt: String,
val modifiedAt: String,
@Ignore
val lastMessage: String? = null,
val feedbackType: ChatFeedbackType? = null) {
constructor(
conversationId: String,
status: String,
createdAt: String,
modifiedAt: String,
feedbackType: ChatFeedbackType):
this(conversationId,status,createdAt,modifiedAt,null,feedbackType)
}
- 这假设您有一个用于 ChatFeedbackType 的 TypeConverter
以上为例(feedbackType为了方便使用String)
还有道:-
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(entities: List<ConversationEntity>)
并使用:-
val conversations = listOf<ConversationEntity>(
ConversationEntity("Conv1","blah","2021-06-25 09:00:00","2021-06-25 10:00:00","NONE"),
ConversationEntity("Conv2","blah","2021-06-25 09:00:00","2021-06-25 10:00:00","NONE"),
ConversationEntity("Conv1","blah","2021-06-26 09:00:00","2021-06-26 10:00:00","NONE")
)
dao.insert(conversations)
那么 运行 之后的 ConversationEntity table 是:-
- 即已添加两行并替换第一行。
然而
忽略 field/variable 使得 Room 永远不会如此有效地填充该值,这使得被忽略的字段在实体中编码时变得毫无用处。
例如,如果您想通过基于查询的计算来填充 lastMessage
,举个例子:-
@Query("SELECT *, 'calculated data' AS lastMessage FROM conversationentity")
fun getConversations(): List<ConversationEntity>
- 您可能认为会用值
calculated data
填充被忽略的 lastMessage field/variable(文字而不是表达式(可能是子查询))
- 文字已用于 convenience/brevity
- 但是 Room 会发出警告,例如
warning: The query returns some columns [lastMessage] which are not used by ....
并且由于 room 的构造函数 used/selected 是在提取 ConversationEntity 时添加的不完整构造函数,因此计算出的值未放入 lastMessage
field/variable 中(即使它可用)。
我建议,如果打算从数据库中填充被忽略的值,您将实体视为部分 class 并将 POJO 作为嵌入实体的完整 class .例如
有 ConversationEntity 作为 :-
@Entity
data class ConversationEntity(
@PrimaryKey val conversationId: String,
val status: String,
val createdAt: String,
val modifiedAt: String,
val feedbackType: String? = null) {
}
对于 demo/example,- String 而不是 ChatFeedbackType
然后有一个 POJO 例如
data class ConversationEntityPojo (
@Embedded
var conversationEntity: ConversationEntity,
var lastMessage: String?
)
- 因此,正如您所见,既不需要构造函数也不需要 @Ignore,而是更完整的 POJO。
从之前用于测试的代码开始,但现在使用修改后的实体和 POJO,然后使用以下 @Query 进行演示:-
@Query("SELECT * FROM conversationentity")
fun getConversationsEntityOnly(): List<ConversationEntity>
@Query("SELECT *, 'calculated data' AS lastMessage FROM conversationentity")
fun getConversationsEntityOnlyWithLastMessage(): List<ConversationEntity>
@Query("SELECT * FROM conversationentity")
fun getConversationsPOJO(): List<ConversationEntityPojo>
@Query("SELECT *,'calculated data' AS lastMessage FROM conversationentity")
fun getConversationPOJOWithLastMessage(): List<ConversationEntityPojo>
然后使用 :-
.... code from previous example
dao.insert(conversations)
for(c: ConversationEntity in dao.getConversationsEntityOnly()) {
Log.d("CONVINFO",
"Conversation is ${c.conversationId} " +
"status is ${c.status} " +
"created ${c.createdAt} " +
"modified ${c.modifiedAt} "
// CANT DO THIS AS ENTITY doesn't have lastMessage field "lastmessage ${c.lastMessage}"
)
}
for (c: ConversationEntity in dao.getConversationsEntityOnlyWithLastMessage()) {
Log.d("CONVINFO",
"Conversation is ${c.conversationId} " +
"status is ${c.status} " +
"created ${c.createdAt} " +
"modified ${c.modifiedAt} "
// CANT DO THIS AS ENTITY doesn't have lastMessage field "lastmessage ${c.lastMessage}"
)
}
for(c: ConversationEntityPojo in dao.getConversationsPOJO()) {
Log.d("CONVINFO",
"Conversation is ${c.conversationEntity.conversationId} " +
"status is ${c.conversationEntity.status} " +
"created ${c.conversationEntity.createdAt} " +
"modified ${c.conversationEntity.modifiedAt} " +
"lastmessage ${c.lastMessage}") /* Will not be populated as lastMessage is not available in extracted data*/
}
for(c: ConversationEntityPojo in dao.getConversationPOJOWithLastMessage()) {
Log.d("CONVINFO",
"Conversation is ${c.conversationEntity.conversationId} " +
"status is ${c.conversationEntity.status} " +
"created ${c.conversationEntity.createdAt} " +
"modified ${c.conversationEntity.modifiedAt} " +
"lastmessage ${c.lastMessage}") /* can be used */
}
那么结果就是:-
2021-06-27 12:26:38.919 D/CONVINFO: Conversation is Conv2 status is blah created 2021-06-25 09:00:00 modified 2021-06-25 10:00:00
2021-06-27 12:26:38.919 D/CONVINFO: Conversation is Conv1 status is blah created 2021-06-26 09:00:00 modified 2021-06-26 10:00:00
2021-06-27 12:26:38.920 D/CONVINFO: Conversation is Conv2 status is blah created 2021-06-25 09:00:00 modified 2021-06-25 10:00:00
2021-06-27 12:26:38.920 D/CONVINFO: Conversation is Conv1 status is blah created 2021-06-26 09:00:00 modified 2021-06-26 10:00:00
2021-06-27 12:26:38.924 D/CONVINFO: Conversation is Conv2 status is blah created 2021-06-25 09:00:00 modified 2021-06-25 10:00:00 lastmessage null
2021-06-27 12:26:38.924 D/CONVINFO: Conversation is Conv1 status is blah created 2021-06-26 09:00:00 modified 2021-06-26 10:00:00 lastmessage null
2021-06-27 12:26:38.926 D/CONVINFO: Conversation is Conv2 status is blah created 2021-06-25 09:00:00 modified 2021-06-25 10:00:00 lastmessage calculated data
2021-06-27 12:26:38.927 D/CONVINFO: Conversation is Conv1 status is blah created 2021-06-26 09:00:00 modified 2021-06-26 10:00:00 lastmessage calculated data
我的数据库 table 是
@Entity
internal data class ConversationEntity(
@PrimaryKey val conversationId: String,
val status: String,
val createdAt: String,
val modifiedAt: String,
val lastMessage: String? = null,
val feedbackType: ChatFeedbackType? = null
)
我想在 lastMessage
上使用 @Ignore
,但出现以下错误。
@Entity
internal data class ConversationEntity(
@PrimaryKey val conversationId: String,
val status: String,
val createdAt: String,
val modifiedAt: String,
@Ignore
val lastMessage: String? = null,
val feedbackType: ChatFeedbackType? = null)
我得到的错误
Entities and POJOs must have a usable public constructor. You can have an empty constructor or a constructor whose parameters match the fields (by name and type).
这里有什么问题?
我的道是
@Insert(onConflict = OnConflictStrategy.REPLACE)
abstract suspend fun saveConversations(entities: List<ConversationEntity>)
我目前的数据库版本是6。我是否还需要编写迁移查询来添加忽略?
将这个class用于实体
class ConversationEntity (){
@PrimaryKey
val conversationId: String
val status: String
val createdAt: String
val modifiedAt: String
@Ignore
val lastMessage: String? = null
val feedbackType: ChatFeedbackType? = null
}
当使用 @Ignore 时,@Ignore 不包含在 table 中,因此 Room 需要一个可用于 inserting/extracting 行的构造函数,而不是完整的默认构造函数。
因此您需要添加一个不包含 lastMessage
的 suitable 构造函数我相信,在解决构造函数问题后,您会遇到一个问题,因为 Conversation 不是 public。您可以通过删除 internal 关键字来解决此问题。
例如
@Entity
data class ConversationEntity(
@PrimaryKey val conversationId: String,
val status: String,
val createdAt: String,
val modifiedAt: String,
@Ignore
val lastMessage: String? = null,
val feedbackType: ChatFeedbackType? = null) {
constructor(
conversationId: String,
status: String,
createdAt: String,
modifiedAt: String,
feedbackType: ChatFeedbackType):
this(conversationId,status,createdAt,modifiedAt,null,feedbackType)
}
- 这假设您有一个用于 ChatFeedbackType 的 TypeConverter
以上为例(feedbackType为了方便使用String)
还有道:-
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(entities: List<ConversationEntity>)
并使用:-
val conversations = listOf<ConversationEntity>(
ConversationEntity("Conv1","blah","2021-06-25 09:00:00","2021-06-25 10:00:00","NONE"),
ConversationEntity("Conv2","blah","2021-06-25 09:00:00","2021-06-25 10:00:00","NONE"),
ConversationEntity("Conv1","blah","2021-06-26 09:00:00","2021-06-26 10:00:00","NONE")
)
dao.insert(conversations)
那么 运行 之后的 ConversationEntity table 是:-
- 即已添加两行并替换第一行。
然而
忽略 field/variable 使得 Room 永远不会如此有效地填充该值,这使得被忽略的字段在实体中编码时变得毫无用处。
例如,如果您想通过基于查询的计算来填充 lastMessage
,举个例子:-
@Query("SELECT *, 'calculated data' AS lastMessage FROM conversationentity")
fun getConversations(): List<ConversationEntity>
- 您可能认为会用值
calculated data
填充被忽略的 lastMessage field/variable(文字而不是表达式(可能是子查询))- 文字已用于 convenience/brevity
- 但是 Room 会发出警告,例如
warning: The query returns some columns [lastMessage] which are not used by ....
并且由于 room 的构造函数 used/selected 是在提取 ConversationEntity 时添加的不完整构造函数,因此计算出的值未放入lastMessage
field/variable 中(即使它可用)。
我建议,如果打算从数据库中填充被忽略的值,您将实体视为部分 class 并将 POJO 作为嵌入实体的完整 class .例如
有 ConversationEntity 作为 :-
@Entity
data class ConversationEntity(
@PrimaryKey val conversationId: String,
val status: String,
val createdAt: String,
val modifiedAt: String,
val feedbackType: String? = null) {
}
-
对于 demo/example,
- String 而不是 ChatFeedbackType
然后有一个 POJO 例如
data class ConversationEntityPojo (
@Embedded
var conversationEntity: ConversationEntity,
var lastMessage: String?
)
- 因此,正如您所见,既不需要构造函数也不需要 @Ignore,而是更完整的 POJO。
从之前用于测试的代码开始,但现在使用修改后的实体和 POJO,然后使用以下 @Query 进行演示:-
@Query("SELECT * FROM conversationentity")
fun getConversationsEntityOnly(): List<ConversationEntity>
@Query("SELECT *, 'calculated data' AS lastMessage FROM conversationentity")
fun getConversationsEntityOnlyWithLastMessage(): List<ConversationEntity>
@Query("SELECT * FROM conversationentity")
fun getConversationsPOJO(): List<ConversationEntityPojo>
@Query("SELECT *,'calculated data' AS lastMessage FROM conversationentity")
fun getConversationPOJOWithLastMessage(): List<ConversationEntityPojo>
然后使用 :-
.... code from previous example
dao.insert(conversations)
for(c: ConversationEntity in dao.getConversationsEntityOnly()) {
Log.d("CONVINFO",
"Conversation is ${c.conversationId} " +
"status is ${c.status} " +
"created ${c.createdAt} " +
"modified ${c.modifiedAt} "
// CANT DO THIS AS ENTITY doesn't have lastMessage field "lastmessage ${c.lastMessage}"
)
}
for (c: ConversationEntity in dao.getConversationsEntityOnlyWithLastMessage()) {
Log.d("CONVINFO",
"Conversation is ${c.conversationId} " +
"status is ${c.status} " +
"created ${c.createdAt} " +
"modified ${c.modifiedAt} "
// CANT DO THIS AS ENTITY doesn't have lastMessage field "lastmessage ${c.lastMessage}"
)
}
for(c: ConversationEntityPojo in dao.getConversationsPOJO()) {
Log.d("CONVINFO",
"Conversation is ${c.conversationEntity.conversationId} " +
"status is ${c.conversationEntity.status} " +
"created ${c.conversationEntity.createdAt} " +
"modified ${c.conversationEntity.modifiedAt} " +
"lastmessage ${c.lastMessage}") /* Will not be populated as lastMessage is not available in extracted data*/
}
for(c: ConversationEntityPojo in dao.getConversationPOJOWithLastMessage()) {
Log.d("CONVINFO",
"Conversation is ${c.conversationEntity.conversationId} " +
"status is ${c.conversationEntity.status} " +
"created ${c.conversationEntity.createdAt} " +
"modified ${c.conversationEntity.modifiedAt} " +
"lastmessage ${c.lastMessage}") /* can be used */
}
那么结果就是:-
2021-06-27 12:26:38.919 D/CONVINFO: Conversation is Conv2 status is blah created 2021-06-25 09:00:00 modified 2021-06-25 10:00:00
2021-06-27 12:26:38.919 D/CONVINFO: Conversation is Conv1 status is blah created 2021-06-26 09:00:00 modified 2021-06-26 10:00:00
2021-06-27 12:26:38.920 D/CONVINFO: Conversation is Conv2 status is blah created 2021-06-25 09:00:00 modified 2021-06-25 10:00:00
2021-06-27 12:26:38.920 D/CONVINFO: Conversation is Conv1 status is blah created 2021-06-26 09:00:00 modified 2021-06-26 10:00:00
2021-06-27 12:26:38.924 D/CONVINFO: Conversation is Conv2 status is blah created 2021-06-25 09:00:00 modified 2021-06-25 10:00:00 lastmessage null
2021-06-27 12:26:38.924 D/CONVINFO: Conversation is Conv1 status is blah created 2021-06-26 09:00:00 modified 2021-06-26 10:00:00 lastmessage null
2021-06-27 12:26:38.926 D/CONVINFO: Conversation is Conv2 status is blah created 2021-06-25 09:00:00 modified 2021-06-25 10:00:00 lastmessage calculated data
2021-06-27 12:26:38.927 D/CONVINFO: Conversation is Conv1 status is blah created 2021-06-26 09:00:00 modified 2021-06-26 10:00:00 lastmessage calculated data