简体   繁体   中英

How can I prevent duplicated insert in oracle database with Java?

Let me give the example first. It is a log table.

User A subscribe the service A = OK
User A unsubscribe the service A = OK
User A subscribe the service A again = OK
User A subscribe the service A again = , because you can't subscribe same service at the same time. ,因为您无法同时订阅相同的服务。

Sometimes the client goes crazy and send 5 subscribe requests at the same time ( 4 tomcat servers behind), if I do nothing in this situation then 5 same records will be inserted.

As you can see, I can't use unique constraint here. I guess perhaps I can use some single thread block in Oracle, but not sure.. I tried "merge" , but I guess it is used in specific records instead of last record.

begin single thread

  1. select the last record
  2. if the is the same then don't insert. 是相同的,则不要插入。
  3. if the not the same then insert. 不相同则插入。 end single thread

Is it possible and how to achieve ?

  1. Perhaps you need to check for the user id , and service type . if same user trying to subscribe same service before the previous subcribed service is performed, then alert the user .

  2. or maybe you want to limit the user to subscribe in only some given duration, say: user can only subscribe same service in each 1 day

  3. You can update the record if the record already exist, for example:

Make a query to check if the record with particular user and service is exist:

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

If the query return any result, means its exist. then do update:

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

else, if no result returned, means the user haven't subscribe the service. then insert record:

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

I think you could solve this problem with constraint. When user subscribes it inserts a row when it unsubscribes it deletes it. A row must be unique for same user and same service.

If you do not want to delete rows add ACTIVE column to this table and make constraint on USER + SERVICE + ACTIVE.

I do not fully understand your problem, but it seems you need to implement mutual exclusion somewhere. Have you tried with a SELECT ... FOR UPDATE?

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

I tried "MERGE" and subquery to solve this case. By the way, this problem is only happened when subscribe. First, I get the status(subscribe or unsubscribe) from the last record of a user and the service. If the last status in table is 'subscribe', means this subscribed request might be the duplicated one.

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');

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM