如何使用Java防止oracle数据库中的重复插入?

时间:2013-12-23 07:11:03

标签: java sql multithreading oracle

首先让我举一个例子。这是一张日志表。

用户A订阅服务A = OK
 用户A取消订阅服务A = OK
 用户A再次订阅服务A = OK
 用户A再次订阅服务A = 不行,因为您无法同时订阅相同的服务。

有时客户端发疯并同时发送5个订阅请求(后面有4个tomcat服务器),如果我在这种情况下什么都不做,那么就会插入5个相同的记录。

如您所见,我不能在这里使用唯一约束。 我想也许我可以在Oracle中使用一些单线程块,但不确定.. 我试过“合并”,但我猜它是用于特定记录而不是最后一条记录。

开始单线程

  1. 选择最后一条记录
  2. 如果最后一条记录相同,则不要插入。
  3. 如果最后一条记录不相同,则插入。 结束单线程
  4. 是否有可能以及如何实现?

4 个答案:

答案 0 :(得分:1)

  1. 也许您需要检查user idservice type。如果同一user尝试在执行上一个订阅的service之前订阅相同的service,则提醒user

  2. 或者您可能希望将user限制为仅在某段时间内订阅,例如: user每天只能订阅相同的服务 < / p>

  3. 如果记录已存在,您可以更新记录,例如:

  4. 进行查询以检查具有特定用户和服务的记录是否存在:

    SELECT * FROM table WHERE userid = userid AND serviceid=serviceid
    

    如果查询返回任何结果,则表示存在。然后做更新:

    UPDATE table SET column1='value', column2='value2' ... WHERE userid = userid AND serviceid = serviceid
    

    否则,如果没有返回结果,则表示用户尚未订阅该服务。然后插入记录:

    INSERT INTO table(column1, column2, ...) values ('value1', 'value2', ...)
    

答案 1 :(得分:1)

我认为你可以用约束来解决这个问题。当用户订阅它时,在取消订阅时插入一行将其删除。对于相同的用户和相同的服务,行必须是唯一的。

如果您不想删除行,请在此表中添加ACTIVE列,并对USER + SERVICE + ACTIVE进行约束。

答案 2 :(得分:0)

我不完全理解你的问题,但似乎你需要在某处实现互斥。你尝试过SELECT ... FOR UPDATE吗?

http://www.techonthenet.com/oracle/cursors/for_update.php

答案 3 :(得分:0)

我试过“MERGE”和子查询来解决这个问题。 顺便说一句,这个问题只发生在订阅时。首先,我从用户和服务的最后一条记录中获取状态(订阅或取消订阅)。如果表中的最后一个状态是“subscribe”,则表示此订阅的请求可能是重复的请求。

MERGE INTO subscr_log M 
  USING
  (SELECT status
  FROM  subscr_log
  WHERE rid=
    (SELECT MAX(rid)
    FROM monthly_subscr_log
    WHERE SCRID    ='123456'
    AND service_item='CHANNEL1'
    )
  ) C 
ON (C.status ='SUB' ) -- try to see the last record is subscribe or not
WHEN MATCHED THEN
   UPDATE  SET M.REASON='N/A' WHERE M.STATUS='XXXXXXX' --do impossible sql
WHEN NOT MATCHED THEN
     INSERT VALUES  (9999,8888,'x','x','x','x','x','x','x','x','x',sysdate,'x','x','x','x');