2017-08-14 234 views
1

我试图用Java,Spring,Hibernate和Oracle SQL实现一个计数器。每个记录代表一个计数,按给定的时间戳记。假设每条记录都是按分钟唯一标识的,每条记录都包含一个计数列。该服务应该期望收到大量的并发请求,并且我的更新可能是同一记录的计数器列。Hibernate并发在saveOrUpdate上创建重复记录

在我的表,如果记录不存在,只是在插入的记录,否则设置它的数量为1,按时间戳查找记录,并通过1

增加其现有的计数器列为了确保我们保持数据的一致性和完整性,我使用悲观锁定。例如,如果20个计数同时进入,并且不一定是同一个用户,那么我们可能会在更新之前从该记录的陈旧读取覆盖该记录。通过锁定,我确保如果有20个计数进入,数据库的净效应应该代表20个计数。

所以锁定是好的,但问题是,如果记录从来没有存在过,并且我们有两个或多个并发请求来试图更新尚未存在的记录,我观察到重复记录被插入是因为我们无法锁定尚不存在的记录。我们如何确保表中没有创建重复项?它应该通过Oracle来控制吗?或者我可以通过我的应用程序和Hibernate来管理这个吗?

谢谢。

回答

0

一个是为了避免这种问题,完全可以在您实际查询数据时生成计数。 Oracle有一个分析函数ROW_NUMBER(),它可以为查询的结果集中的每个记录分配一个行号。作为一个粗略的例子,考虑以下查询:

SELECT 
    ts, 
    ROW_NUMBER() OVER (ORDER BY ts) rn 
FROM yourTable 

你想会是在rn列,代表因为在表中的第一项出现的记录数的计数。当然,你可以进一步限制查询。

这种方法对删除记录非常有效,因为计数总是从1开始。一个缺点是Hibernate不支持行号功能。您必须以本机查询或存储过程的方式运行此操作。