2016-06-01 69 views
0

我在DB中有一個學生表,其中有名稱,主題和標記字段。 1位學生可以在此表中爲不同科目設置多個記錄。在字符串的情況下應該如何使用同步?

我有有這樣的更新方法的學生DAO類:

public marks updateStudent(String name, String subject, int marks){ 
//this method first check if the record of this name and subject is there in DB 
    if(getStudentRecordFromDB(name, subject){ 
     //then return marks for this student 

    }else{ 
     //insert the record in DB and return marks 
     insertRecord(name, subject, marks); 

    } 

} 

這種方法可以同時被多個線程對同一個學生的名字和主題被調用。我想讓它只在多線程更新相同名稱和主題的情況下同步。 所以我想在名稱+主題的字符串上同步這種方法,但由於這是一個不好的做法,由於字符串常量池(它存在的字符串)也不給我保證的結果,所以我想使用一些更好的解決方案。 我不想在DAO.class上同步,因爲我只想在同步記錄更新的情況下進行同步。 什麼應該是最好的方式來做到這一點?

+0

你應該不需要同步數據庫更新 - 你爲什麼要這樣做? –

+0

DB側沒有限制爲同一名稱和主題插入多個記錄。不幸的是我不能在DB中改變任何東西。所以我必須在我的java服務中同步它。我知道這可能是一個糟糕的設計,但我無法幫助它,我想要一個解決方案,使它只能從Java代碼工作。 –

+4

您想在這裏使用數據庫事務,並且想要在'getStudentRecordFromDB'方法中鎖定記錄以進行更新(或使用樂觀鎖定)。儘管技術上可以在一個字符串上進行同步(在同步之前使用'String.intern'方法來獲得一個唯一的實例),但它並不能保護您免受在同一數據庫上運行的另一個應用程序的影響,也不能保護您的多個實例應用正在運行。 –

回答

1

這個方法可以同時被多個線程調用同一個學生的名字和主題。

這樣做的一種方法是在數據庫上創建一個唯一的限制,如果數據庫已經有student-name/subject組合,將會拋出異常。所以,你會:

  1. 查詢的學生姓名/主題
  2. 如果不存在的話,儘量將其插入到數據庫
  3. 如果失敗,那麼請查詢再次以防範競賽條件。
  4. 如果仍然不存在,則拋出數據庫異常

可以與同步執行此操作雖然它是不平凡。你可以這樣做:

  1. 創建一個包裝的學生姓名/主題,其中hashcode()equals()使用這些領域的一個對象。
  2. 無論何時您去做手術,都可以使用ConcurrentHashMapputIfAbsent(...)您的StudentNameSubject。該值可以只是一些隨機常數對象,因爲您不能使用null並且沒有ConcurrentHashSet
  3. 然後在您創建的StudentNameSubject上同步,或者如果地圖已經存在,則同步。
  4. 在​​塊內執行數據庫操作。
  5. 完成​​塊後,您可以從地圖中刪除條目。
相關問題