我实现了以下模式,用于计算用户的按钮点击次数。例如,如果用户单击apple按钮,我希望将类型存储为主键,这将是一个唯一的条目,后面是用户点击apple按钮的次数计数,对于每一次点击,我还将节省与这些点击相关的时间。所以我试图学习room数据库,想了解如何使用新的关联计数和时间戳更新唯一的水果类型行。我需要查询这个表吗 getByType(type)
获取现有数据条目,然后每次使用新的计数和时间戳值对其进行更新,或者是否有更好的方法使用room api进行更新
@Entity
data class ClickEntity(
@PrimaryKey
val type: String,
val clickCount: Int? = null,
val clickTime: Long? = null
)
@Dao
internal interface ClickEntityDao {
@Query("SELECT * FROM ClickEntity ORDER BY type")
fun getAll(): List<ClickEntity>
@Query("SELECT * FROM ClickEntity WHERE type=:type")
fun getByType(entity: ClickEntity): ClickEntity
// QUESTION: type, count, time -> how do I increment counter and update time while updating an existing entry
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun update(entity: ClickEntity)
@Query("DELETE FROM ClickEntity")
fun clear()
}
2条答案
按热度按时间2w3kk1z51#
您可以执行以下操作
然后增加
t3psigkw2#
我相信以下几点可以满足您的需求:-
例如:-
结果:-
i、 e.在更新计数增加且当前时间相应设置后,当插入计数和时间为0时。因此,无需获取数据然后应用(只要您知道应该使用的类型,如果它等同于按钮)。
补充再评论
我仍然需要在更新和插入之前插入一次!是否有一个较短的版本可同时插入更新。
是的,也许吧。然而,如果你有一个按钮,那么我建议在你知道应该有按钮时插入。
如果应用程序针对的是具有sqlite版本3.24.0(android api 30+版本11+)的android版本,那么您可以使用upsert(插入带有on conflict()do update子句)。
例如
注意:上面的代码没有经过测试,但是显示了一个语法错误(可能是因为目标android版本)。
另一种选择是使用插入或替换,这只是使用:-
但是你必须找回计数。
但是,更复杂的解决方案可能是使用子查询获取类型的计数+1。这很复杂,因为第一次插入时没有计数。这可以使用sqlite解决
coalesce
功能。这需要@query,因为@insert需要一个实体对象。因此,插入或替换(更新但实际删除和插入以执行更新)的解决方案可以是:-因此:-
如果该类型不存在,它将插入一个新行,以便:
尝试获取类型的clickcount列的当前值,但由于不存在此类行,因此返回null,因此coalesce函数返回-1,并添加1,因此新行的计数为0。
使用sqlite的
strftime
函数,并将其乘以1000,使其与android时间戳内联(添加毫秒)。如果该类型存在,则将用另一行替换该行,以便:
从现有行中查找计数并添加1
示例(插入或替换选项):-
根据上述代码,除了上述dao的更改/添加之外,还添加了以下内容(不是upsert):-
然后,数据库看起来像(所有android studio show):-
banana显示当前_时间戳是如何存储的,这将导致问题。
pear只使用strftime(“%s”、“now”),即没有毫秒
正如您所看到的,葡萄和杏都是预期的,即数量增加了。