房间数据库重复相同的主键项
Roomdatabase Duplicates Same Primarykey Item
我正在从通知中获取消息并将其保存到 Roomdatabase。问题是我使用用户名作为主键,但是当数据到来时具有相同的主键,roomdatabase 将其保存为一个新对象。我用了 OnConflictStrategy.REPLACE 但它不起作用。这是我的 类。注意:我通过使用单独的实体对象来保存用户和消息。
@Entity
data class UserEntity(
@PrimaryKey(autoGenerate = false) val user: String,
val lastMessage: String,
val lastTime: String
)
DAO
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertUser(entity: UserEntity)
传入数据
val from = bundle.getString(NotificationCompat.EXTRA_TITLE)
val message = bundle.getString(NotificationCompat.EXTRA_TEXT)
val filteredFrom = from?.replace(
"\(.*\)".toRegex(),
""
)?.filter {!it.isWhitespace()}
保存方法
repository.addUserToRoomDatabase(
UserEntity(
user = filteredFrom,
lastMessage = message,
lastTime = time
)
)
我相信您的问题不是由于 Room 的明显处理不当造成的,而是问题出在其他地方,如果您使用 App Inspection 检查实际数据库,那么您会发现确实如此。
演示
使用你的 UserEntity class 和你的 insertUser 函数(虽然没有暂停)和一个额外的 DAO 来提取数据(所以 @Dao 注释 class AllDAO)是:-
@Dao
interface AllDAO {
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertUser(entity: UserEntity)
@Query("SELECT * FROM userentity")
fun getAllUsers(): List<UserEntity>
}
连同下面的演示(以及一个合适的@Database注解class):-
class MainActivity : AppCompatActivity() {
lateinit var db: TheDatabase
lateinit var dao: AllDAO
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
db = TheDatabase.getInstance(this)
dao = db.getAllDAO()
dao.insertUser(UserEntity("Fred","1st Fred","0000"))
dao.insertUser(UserEntity("Mary","1st Mary","1111"))
dao.insertUser(UserEntity("Jane","1st Jane","2222"))
logAllUsers("_RUN1")
dao.insertUser(UserEntity("Fred","2nd Fred","4444"))
dao.insertUser(UserEntity("Mary","2nd Mary","5555"))
dao.insertUser(UserEntity("Jane","2nd Jane","6666"))
logAllUsers("_RUN2")
}
fun logAllUsers(prefix: String) {
for (u in dao.getAllUsers()) {
Log.d("USERINFO${prefix}","User is ${u.user} Last Message is ${u.lastMessage} LastTime is ${u.lastTime}")
}
}
}
结果日志中包含:-
2022-04-28 05:50:34.735 D/USERINFO_RUN1: User is Fred Last Message is 1st Fred LastTime is 0000
2022-04-28 05:50:34.735 D/USERINFO_RUN1: User is Mary Last Message is 1st Mary LastTime is 1111
2022-04-28 05:50:34.735 D/USERINFO_RUN1: User is Jane Last Message is 1st Jane LastTime is 2222
2022-04-28 05:50:34.741 D/USERINFO_RUN2: User is Fred Last Message is 2nd Fred LastTime is 4444
2022-04-28 05:50:34.742 D/USERINFO_RUN2: User is Mary Last Message is 2nd Mary LastTime is 5555
2022-04-28 05:50:34.742 D/USERINFO_RUN2: User is Jane Last Message is 2nd Jane LastTime is 6666
也就是说,从输出来看,行被替换而不是重复。
使用 App Inspection,这证实了这种情况,因为它只显示了最后 3 个被替换的行:-
如果using/running以下查询使用应用程序检查SELECT rowid,* FROM userentity
则显示:-
这进一步证实了 Room 的行为符合预期。
也就是说,当第一个 运行 时,前 3 个插入将创建具有 rowids 1,2 和 3 的行。
插入第二组时,删除 rowid 1(用户 Fred)的行并插入新行,rowid 将是下一个,即 4,依此类推 (2 --> 5, 3 --> 6)。
如果您确实看到看似重复的行,则很可能用户实际上并不相同。您也许可以通过 App Inspection 使用查询 SELECT rowid,length(user),* FROM userentity
此处再次使用 App Inspection 中的查询使用 INSERT INTO userentity VALUES ('Fred ','ooops','9999')
插入明显错误的行(注意 Fred 之后的 space)
Fred 似乎为 Fred 复制了一行,但 space 有所不同。使用第二个查询可以看出,是的,有 2 行 Fred,但第二个查询有 5 作为 Fred 的长度。
由于您正在“过滤”,那么也许这就是您的问题所在。
我正在从通知中获取消息并将其保存到 Roomdatabase。问题是我使用用户名作为主键,但是当数据到来时具有相同的主键,roomdatabase 将其保存为一个新对象。我用了 OnConflictStrategy.REPLACE 但它不起作用。这是我的 类。注意:我通过使用单独的实体对象来保存用户和消息。
@Entity
data class UserEntity(
@PrimaryKey(autoGenerate = false) val user: String,
val lastMessage: String,
val lastTime: String
)
DAO
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertUser(entity: UserEntity)
传入数据
val from = bundle.getString(NotificationCompat.EXTRA_TITLE)
val message = bundle.getString(NotificationCompat.EXTRA_TEXT)
val filteredFrom = from?.replace(
"\(.*\)".toRegex(),
""
)?.filter {!it.isWhitespace()}
保存方法
repository.addUserToRoomDatabase(
UserEntity(
user = filteredFrom,
lastMessage = message,
lastTime = time
)
)
我相信您的问题不是由于 Room 的明显处理不当造成的,而是问题出在其他地方,如果您使用 App Inspection 检查实际数据库,那么您会发现确实如此。
演示
使用你的 UserEntity class 和你的 insertUser 函数(虽然没有暂停)和一个额外的 DAO 来提取数据(所以 @Dao 注释 class AllDAO)是:-
@Dao
interface AllDAO {
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertUser(entity: UserEntity)
@Query("SELECT * FROM userentity")
fun getAllUsers(): List<UserEntity>
}
连同下面的演示(以及一个合适的@Database注解class):-
class MainActivity : AppCompatActivity() {
lateinit var db: TheDatabase
lateinit var dao: AllDAO
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
db = TheDatabase.getInstance(this)
dao = db.getAllDAO()
dao.insertUser(UserEntity("Fred","1st Fred","0000"))
dao.insertUser(UserEntity("Mary","1st Mary","1111"))
dao.insertUser(UserEntity("Jane","1st Jane","2222"))
logAllUsers("_RUN1")
dao.insertUser(UserEntity("Fred","2nd Fred","4444"))
dao.insertUser(UserEntity("Mary","2nd Mary","5555"))
dao.insertUser(UserEntity("Jane","2nd Jane","6666"))
logAllUsers("_RUN2")
}
fun logAllUsers(prefix: String) {
for (u in dao.getAllUsers()) {
Log.d("USERINFO${prefix}","User is ${u.user} Last Message is ${u.lastMessage} LastTime is ${u.lastTime}")
}
}
}
结果日志中包含:-
2022-04-28 05:50:34.735 D/USERINFO_RUN1: User is Fred Last Message is 1st Fred LastTime is 0000
2022-04-28 05:50:34.735 D/USERINFO_RUN1: User is Mary Last Message is 1st Mary LastTime is 1111
2022-04-28 05:50:34.735 D/USERINFO_RUN1: User is Jane Last Message is 1st Jane LastTime is 2222
2022-04-28 05:50:34.741 D/USERINFO_RUN2: User is Fred Last Message is 2nd Fred LastTime is 4444
2022-04-28 05:50:34.742 D/USERINFO_RUN2: User is Mary Last Message is 2nd Mary LastTime is 5555
2022-04-28 05:50:34.742 D/USERINFO_RUN2: User is Jane Last Message is 2nd Jane LastTime is 6666
也就是说,从输出来看,行被替换而不是重复。
使用 App Inspection,这证实了这种情况,因为它只显示了最后 3 个被替换的行:-
如果using/running以下查询使用应用程序检查SELECT rowid,* FROM userentity
则显示:-
这进一步证实了 Room 的行为符合预期。
也就是说,当第一个 运行 时,前 3 个插入将创建具有 rowids 1,2 和 3 的行。
插入第二组时,删除 rowid 1(用户 Fred)的行并插入新行,rowid 将是下一个,即 4,依此类推 (2 --> 5, 3 --> 6)。
如果您确实看到看似重复的行,则很可能用户实际上并不相同。您也许可以通过 App Inspection 使用查询 SELECT rowid,length(user),* FROM userentity
此处再次使用 App Inspection 中的查询使用 INSERT INTO userentity VALUES ('Fred ','ooops','9999')
插入明显错误的行(注意 Fred 之后的 space)
Fred 似乎为 Fred 复制了一行,但 space 有所不同。使用第二个查询可以看出,是的,有 2 行 Fred,但第二个查询有 5 作为 Fred 的长度。
由于您正在“过滤”,那么也许这就是您的问题所在。