楽観的同時実行制御を学習しようとしています。
次のプログラム
- セッションを開き、テーブルに行を作成します: id=1 name = "raj"、セッションをコミットして閉じます
- 最初に 3 秒間スリープするスレッドを開始します。次に、session2 を開き、id =1 の人物を name = "raj10" で更新します。その後、session2 が閉じられます。
- session3 で、同じ db 行 (id=1) を変更します。ただし、この行は、ステップ 2 のスレッドが同じ db 行をロードする前にロードされます。そして、セッション 3 では、ロードされた db 行が更新されます (これは、ステップ 2 のスレッドによって既に変更されているため、古くなります)。だから私はstaleObjectStateExceptionをキャッチします。catch ブロック内で再度読み込み、更新してから保存します。
次の例外が発生します: Exception in thread "main" org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was wrong): [com.raj.hibernate.optimistic.OptPerson#1]
教えてください
- 新しい値で正常に更新するには、catch ブロックに何を含める必要がありますか。
ここで session.merge が役に立ちますか。
final SessionFactory factory = new Configuration().configure() .buildSessionFactory(); Session session = factory.openSession(); session.beginTransaction(); OptPerson optP1 = new OptPerson(); optP1.setName("raj"); session.save(optP1); session.getTransaction().commit(); session.close(); System.out.println("done saving, closed session"); new Thread() { public void run() { try { Thread.sleep(3000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } Session session2 = factory.openSession(); session2.beginTransaction(); OptPerson p1 = (OptPerson) session2.get(OptPerson.class, 1); p1.setName("raj10"); session2.save(p1); session2.getTransaction().commit(); session2.close(); System.out.println("modified person in session2"); } }.start(); Session session3 = factory.openSession(); session3.beginTransaction(); OptPerson p1 = (OptPerson) session3.get(OptPerson.class, 1); System.out.println("read person in session3"); Thread.sleep(8000); try { p1.setName("man"); session3.save(p1); session3.getTransaction().commit(); } catch (StaleObjectStateException ex) { System.out.println("inside catch block"); OptPerson p3 = (OptPerson) session3.get(OptPerson.class, 1); p3.setName("man"); session3.saveOrUpdate(p3); //OptPerson p4 = (OptPerson) session3.merge(p1); session3.getTransaction().commit(); } finally { session3.close(); }