2013-12-23 87 views
0

讓我先舉例。這是一個日誌表。如何防止在Java數據庫中使用重複插入?

用戶A訂閱服務A = OK
用戶A退訂服務A = OK
用戶A訂閱服務一遍= OK
用戶A訂閱服務一遍= 不正常,因爲你無法同時訂閱相同的服務。

有時客戶端發瘋,同時發送5個訂閱請求(後面有4個tomcat服務器),如果我在這種情況下什麼都不做,那麼會插入5個相同的記錄。

正如你所看到的,我不能在這裏使用唯一的約束。 我想也許我可以在Oracle中使用一些單線程塊,但不知道.. 我嘗試過「合併」,但我想它是用於特定記錄而不是最後一條記錄。

開始單線程

  1. 選擇最後一條記錄
  2. 如果最後一個記錄是一樣的,那麼請不要插入。
  3. 如果最後一條記錄是不一樣的話插入。 end single thread

是否可能以及如何實現?

+0

爲什麼你不能使用唯一約束? –

+0

@EvgeniyDorofeev主要是因爲唯一約束將仍然允許「服務A」重複訂閱。 – Baby

+0

@EvgeniyDorofeev:因爲用戶以後可以訂閱和取消訂閱,甚至在一天內再次訂閱。 – Aska

回答

1
  1. 也許你需要檢查的user idservice type。如果相同user試圖訂閱相同的service,然後再執行前面提到的service,則提醒user

  2. 或者也許你想限制user在某些給定的時間認購,說:user只能在每個1天訂閱相同的服務

  3. 如果該記錄已經存在,您可以更新記錄,例如:

進行查詢,以檢查是否存在特別的用戶和服務記錄:

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', ...) 
+0

嗨拉法: 這是一個日誌表。通常,相同的用戶將訂閱服務,並在他/她不感興趣時​​取消訂閱。然後會有兩個記錄:一個用於訂閱,另一個用於取消訂閱。 但是,客戶端代碼(移動設備)中存在未知錯誤,它將同時發送5個訂閱請求。但在這種情況下我只能插入一條記錄。否則,同一用戶會有5個訂閱日誌,這是不需要的。 – Aska

+0

也許你可以更新當前的記錄,即用新的相同的服務請求替換它,而不是添加新的記錄 – Baby

+0

嗨Rafa:我想你的解決方案是「合併」? 如果是這樣,在這種情況下如何在USING塊中編寫代碼?通常情況下它會是「(SELECT COUNT(*)AS CNT FROM SHELF_STATUS WHERE SID ='abcd')C」或其他東西,但在這種情況下,我需要做的是兩步:1.查詢最後一條記錄這個用戶和這個服務2.如果這個記錄是「訂閱」,並且用戶還想訂閱,那麼就像你說的那樣更新它。 – Aska

0

我不完全理解你的問題,但似乎你需要在某個地方實現互斥。您是否嘗試過使用SELECT ... FOR UPDATE?

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

+0

嗨Jorge_B: 如果你訂閱一些月服務,比如說「你可以看所有」,那麼你不能再訂閱,直到你取消訂閱它。 問題是一個客戶端(移動設備)有時會同時發送多個相同的請求(這是一個錯誤),但我只能插入一個訂閱日誌。 在這種情況下,我沒有行被鎖定,所以看起來我不能在這種情況下使用select ..來更新。 – Aska

+0

只是一個想法:讓你的日誌表與一個自動數字序列主鍵一起工作,並只記錄一切。通過這種方式,您可以知道何時發生多次訂閱嘗試錯誤,並將解決此問題(而不是隱藏它) –

+0

我想修復APP中的錯誤,但是,IOS開發團隊無法重現此類問題。有一個對話框要求用戶確認他們是否要訂閱或不訂閱。單擊時,用戶無法執行任何操作,直到後面的流程完成。所以在這種情況下應該可以。 – Aska

1

我想你可以用約束來解決這個問題。當用戶訂閱它時,如果取消訂閱,將刪除它。一行對於同一用戶和同一服務必須是唯一的。

如果您不想刪除行,將ACTIVE列添加到此表中,並對USER + SERVICE + ACTIVE進行約束。

+0

感謝您的建議,但是,我無法刪除這些記錄。這張表是供報告使用的,人們想知道客戶的行爲。 – Aska

+0

但你可以有一個單獨的表鎖定urposes –

+0

看我上次更新 –

0

我試過「MERGE」和子查詢來解決這種情況。 順便說一下,這個問題只發生在訂閱時。首先,我從用戶和服務的最後記錄中獲得狀態(訂閱或取消訂閱)。如果表中的最後一個狀態是'訂閱',則表示這個訂閱的請求可能是重複的。

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'); 
相關問題