更新が失われる状況を回避するために、オプティミスティックロックを実装しようとしています。私のアプリケーションでは、2つのユーザーが同じレコードと最初のユーザーいくつかの変更とそれを更新を取得するとき。この変更は、同じレコードを表示する2番目のユーザーには表示されず、自分で変更を加えて更新します。そのため、最初の人の変更は失われます。これを防ぐために、私は次のように書いていますが、それでも問題は解決しません。私はこのコンセプトに新しいです、問題を特定することはできません。
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();
}
}
前もって感謝します
JPA/Hibernate Optmisticロックは、フィールドを使用して最後に変更されたバージョン(timestamp、longなど)を格納し、セッション内のエンティティのバージョンをデータベース内のエンティティと比較して、変更を保存できるかどうかを確認することで機能します。
これを機能させるには、エンティティに@Versionアノテーションが付けられたフィールドが必要です。
例については、以下を参照してください。
http://www.javacodegeeks.com/2012/11/jpahibernate-version-based-optimistic-concurrency-control.html
これをWebアプリケーションで機能させるには、さらに検討する必要があります。ただし、2人が同じエンティティをロードして編集し、しばらくしてから編集を送信すると、長時間実行されるセッションを使用していない限り、エンティティは両方とも成功する可能性があります。編集中は、フォームの送信時にデータベースから再読み込みされ、入力されて保存されます。
例えばリビジョン1のエンティティ
したがって、これが機能するためには、ロードされた時点でのエンティティリビジョンを格納するフォームを使用して非表示フィールドを送信することを検討できます。したがって、上記の最後のステップで、ユーザー1が送信すると、リビジョンフィールドが1に戻され、DB内のレコードがr2であるため、更新は失敗します。