6

私はオプティミスティックロックをインラインで実装しようとしています。私のアプリケーションでは、2人のユーザーが同じレコードをフェッチし、最初のユーザーがいくつかの変更を加えて更新します。この変更は、同じレコードを表示する第2のユーザーには表示されず、自分で変更を加えて更新します。これにより、最初の人の変化が失われます。これを防ぐために、私は以下を書いていますが、依然として問題は残っています。私はこの概念を初めて熟知しており、問題を特定できません。HibernateとSpringを使用してオプティミスティックロックを実装する

私はdoc 11.3.4を読んでこれを達成しようとしました。自動バージョニングセクションのカスタマイズ。

  • 設定ファイル

    <?xml version="1.0" encoding="UTF-8"?> 
    <beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:mvc="http://www.springframework.org/schema/mvc" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:tx="http://www.springframework.org/schema/tx" 
    xsi:schemaLocation=" 
    http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
    http://www.springframework.org/schema/tx 
    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd 
    http://www.springframework.org/schema/mvc 
    http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"> 
    
    <tx:annotation-driven transaction-manager="txManager"/> 
    
    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
        <property name="dataSource" ref="dataSource"/> 
    </bean> 
    
    <bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate"> 
        <property name="sessionFactory" ref="sessionFactory"/> 
    </bean> 
    
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> 
        <property name="dataSource" ref="dataSource"/> 
        <property name="annotatedClasses"> 
        <list> 
         <value>server.bo.Dept</value> 
         <value>server.bo.Emp</value> 
        </list> 
        </property> 
        <property name="hibernateProperties"> 
        <props> 
         <prop key="hibernate.dialect">org.hibernate.dialect.SQLServer2008Dialect</prop> 
         <prop key="hibernate.show_sql">false</prop> 
        </props> 
        </property> 
    </bean> 
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
        <property name="driverClassName" value="net.sourceforge.jtds.jdbc.Driver"/> 
        <property name="url" value="${db.url}"/> 
        <property name="username" value="${db.username}"/> 
        <property name="password" value="${db.password}"/> 
    </bean> 
    <bean id="deptDAO" class="server.dao.DeptDAOImpl"> 
        <property name="hibernateTemplate" ref="hibernateTemplate"/> 
    </bean> 
    </beans> 
    
  • エンティティークラス

    @Entity 
    @Table(name = "Dept") 
    @org.hibernate.annotations.Entity(dynamicUpdate = true,optimisticLock = OptimisticLockType.ALL) 
    public class Dept{ 
        @Id 
        @GeneratedValue(strategy = GenerationType.AUTO) 
        @Column(name = "ID") 
        Long id; 
    
        @OneToMany(cascade = CascadeType.REMOVE, fetch = FetchType.EAGER, mappedBy = "deptId") 
        @Fetch(FetchMode.SELECT) 
        @OrderBy(value = "id DESC") 
        List<Emp> Emplist; 
    
        public Dept() {} 
        // Getters and setters 
    } 
    
  • DAOのImpl

    public class DeptDAOImpl extends HibernateDaoSupport implements DeptDAO { 
        @Transactional(readOnly = true, propagation = Propagation.REQUIRED, isolation = Isolation.REPEATABLE_READ) 
        public Dept getDeptById(Long id) { 
          Object param[] = new Object[]{id}; 
          String query = "select d from Dept d where d.id=? and d.deleted='0'"; 
          List<Dept> deptDetailsList = getHibernateTemplate().find(query,param); 
          Dept deptDetails = null; 
          if(deptDetailsList !=null && deptDetailsList .size()>0) 
           deptDetails = (Dept)deptDetailsList.get(0); 
          return deptDetails ; 
        } 
    
        @Transactional(readOnly = false, propagation = Propagation.REQUIRED, isolation = Isolation.REPEATABLE_READ) 
        public long updateDept(Dept dept) { 
          if (dept.getId() == null) { 
           getSession().save(dept); 
          } else { 
           getSession().update(dept); 
          } 
          if (dept.getEmplist() != null) { 
            final int size = dept.getEmplist().size(); 
            for (int i = size - 1; i >= 0; i--) { 
             Emp emp = dept.getEmplist().get(i); 
             if (emp.getDeptId() == null) { 
              emp.setDeptId(dept.getId()); 
            } 
            if (RecordStatus.NEW.equals(emp.getRecordStatus())) { 
             getSession().save(emp); 
            } else if (RecordStatus.DELETED.equals(emp.getRecordStatus())) { 
             getSession().delete(emp); 
            } else if (RecordStatus.MODIFIED.equals(emp.getRecordStatus())) { 
             getSession().update(emp); 
            } 
           } 
         } 
         return dept.getId(); 
        } 
    } 
    

ありがとうございます。

答えて

12

JPA/Hibernateオプティミスティックロックは、いくつかのフィールドを使用して最後に修正されたバージョンを保存することによって動作します。タイムスタンプ、ロング)、セッション内のエンティティのバージョンとデータベース内のエンティティのバージョンを比較して、変更を保存できるかどうかを確認します。

これを機能させるには、エンティティに@Versionというアノテーションが付いたフィールドを持つ必要があります。

例を参照してください。 Webアプリケーションで動作するように、このために

http://www.javacodegeeks.com/2012/11/jpahibernate-version-based-optimistic-concurrency-control.html

二人が編集用に同じエンティティをロードして、いくつかの時間後に使用している場合を除き、彼らはおそらく、として成功するの両方彼らの編集を提出するかのようにしかし、さらに考えを必要としある種の長時間実行されているセッションでは、編集中のエンティティがフォーム送信時にデータベースから再読み込みされ、読み込まれて保存されます。

1人の

  • ユーザー編集のための2つの負荷でのリビジョン:1人の
  • ユーザー2つの提出フォームでリビジョン:(R1での)エンティティは、フィールドがバインドされ、ロードされたリビジョン1

    • ユーザー編集のための1つの負荷をでエンティティエンティティが保存されます。リビジョンは1件の提出が形成2.
    • ユーザーである:(R2で)エンティティのエンティティが保存され、フィールドがバインドされ、ロードされます。リビジョンは、あなたが見ることができる動作するように、このためにそう3.

    ですエンティティを格納するフォームで隠しフィールドを送信するときそれがロードされた時点のリビジョン。したがって、上記の最後のステップでは、ユーザー1が送信すると、リビジョンフィールドは1に戻され、r2のようにDB内のレコードが更新されません。

  • +3

    悪意のあるユーザーがこれらの値を変更してシステムを意図しない状態にする可能性があるため、隠しフィールドを使用しないでください。セキュリティのために、サーバー側で状態を維持する必要があります。こんにちはNathan https://www.owasp.org/index.php/Web_Parameter_Tampering – Nathan

    +0

    を参照してください。私はパラメータ改ざんの危険性に精通しています。この画面にアクセスしたユーザーが明らかに編集権限を持っていることを考えれば、ユーザーがバージョン番号を改ざんした結果を教えてください。 –

    +0

    私は何かが欠けていない限り、ユーザーがバージョン番号を任意の値に設定できるという要件はないので、バージョンをユーザー入力から読み取るべきではありません。ユーザーが必要としないものを変更できるようにするのではなく、サーバーはセッションなどでバージョン番号を保持する必要があります。 – Nathan

    関連する問題