2016-06-01 6 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); 

    } 

} 

このメソッドは、同じ生徒の名前と件名のために複数のスレッドで同時に呼び出すことができます。私は同じ名前と主題を更新する複数のスレッドの場合にのみ同期させたいです。 私はこのメソッドをname + subjectの文字列に同期させることを考えましたが、これは文字列定数プール(その文字列の存在)のために結果が得られないという悪い習慣なので、もっと良い解決法を使いたいと思います。 DAO.classで同期させたくないのは、同じレコードが更新された場合にのみ同期したいからです。 これを行う最善の方法は何ですか?

+0

DBアップデートを同期する必要はありません。なぜそれをしたいのですか? –

+0

DB側には、同じ名前と件名のレコードを複数挿入することに制限はありません。残念ながらDBでは何も変更できません。だから私は私のJavaサービスでのみ同期する必要があります。私はそれが悪いデザインかもしれないことは知っているが、私はそれを助けることができないし、私はそれがJavaコードからのみ動作するようにするソリューションが欲しい。 –

+4

ここでデータベーストランザクションを使用し、 'getStudentRecordFromDB'メソッドで更新のためにレコードをロックする(またはオプティミスティックロックを使用する)必要があります。技術的にはString(同期する前に 'String.intern'メソッドを使用して一意のインスタンスを取得)することは技術的に可能ですが、同じデータベース上で動作する別のアプリケーションや、アプリケーションが実行中です。 –

答えて

1

このメソッドは、同じ生徒の名前と件名に対して同時に複数のスレッドで呼び出すことができます。

これを行う1つの方法は、データベースに既に学生名/件名の組み合わせがある場合に例外をスローするデータベースに固有の制限を作成することです。だから、希望:学生名/件名のため

  1. クエリ
  2. それは存在しなかった場合、それが保護するために再びクエリを実行後、失敗した場合、データベース
  3. でそれを挿入しよう競争状態。
  4. それはまだそれが非自明であるが、あなた同期でこれを行うことができ、データベース例外

を投げ、その後存在しない場合。

  1. hashcode()equals()は、これらのフィールドを使用して、生徒名/件名をラップするオブジェクトを作成します。あなたのような何かを行うことができます。
  2. 操作を行うたびに、StudentNameSubjectConcurrentHashMapputIfAbsent(...)を使用してください。 nullを使用することはできず、ConcurrentHashSetも存在しないため、値はランダムな定数オブジェクトになります。
  3. 作成したStudentNameSubjectのいずれかに同期してください。既に存在する場合はマップのものです。
  4. ​​ブロック内でデータベース操作を実行してください。
  5. ​​ブロックを完了した後、マップからエントリを削除できます。
関連する問題