1

楽観的同時実行制御を学習しようとしています。

次のプログラム

  1. セッションを開き、テーブルに行を作成します: id=1 name = "raj"、セッションをコミットして閉じます
  2. 最初に 3 秒間スリープするスレッドを開始します。次に、session2 を開き、id =1 の人物を name = "raj10" で更新します。その後、session2 が閉じられます。
  3. 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]

教えてください

  1. 新しい値で正常に更新するには、catch ブロックに何を含める必要がありますか。
  2. ここで 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();
    }
    
4

0 に答える 0