yyg1107

这家伙很懒,什么都没有留下
posts(15) comments(20) trackbacks(0)
  • BlogJava
  • 联系
  • RSS 2.0 Feed 聚合
  • 管理

公告

联系方式:     



常用链接

  • 我的随笔
  • 我的评论
  • 我的参与
  • 最新评论

留言簿

  • 给我留言
  • 查看公开留言
  • 查看私人留言

随笔分类(11)

  •  axis(1)
  •  hibernate(1)
  •  java(2)
  •  js(2)
  •  other(5)

随笔档案(8)

  • 2008年6月 (1)
  • 2007年8月 (2)
  • 2007年4月 (3)
  • 2006年11月 (2)

文章分类(37)

  •  C++Builder(3)
  •  eclipse(2)
  •  html(4)
  •  java(8)
  •  jbpm(6)
  •  JS(4)
  •  other(4)
  •  question handly!(4)
  •  web容器(1)
  •  workflow(1)

文章档案(36)

  • 2007年4月 (2)
  • 2007年3月 (1)
  • 2007年1月 (2)
  • 2006年12月 (2)
  • 2006年11月 (3)
  • 2006年10月 (11)
  • 2006年9月 (2)
  • 2006年7月 (2)
  • 2006年6月 (1)
  • 2006年5月 (1)
  • 2006年4月 (6)
  • 2006年3月 (3)

新闻档案(1)

  • 2007年1月 (1)

收藏夹(16)

  •  好的BLOG(9)
  •  收藏----blog(7)

JavaBlog

  • amigoxie

matrix

搜索

  •  

积分与排名

  • 积分 - 32776
  • 排名 - 1316

最新评论

  • 1. re: JS实现文本框输入提供选择框的提示功能-1
  • werewrewrwer
  • --wrewrwe
  • 2. re: struts启动的一个错误!
  • 更名struts-config.xml, remove && add struts capability,重新生成一个config.xml。
  • --barryken
  • 3. p
  • 42
  • --2
  • 4. re: hql语句----随机查询取头10条记录[未登录]
  • 没意思,这不就是分页的那一部分代码嘛!
  • --啊啊
  • 5. re: 第一次做成功的AXIS例子[未登录]
  • 楼主:能不能留下你的联系方式!探讨一下相关问题...
  • --hehe

阅读排行榜

  • 1. JS实现文本框输入提供选择框的提示功能-1(7293)
  • 2. 第一次做成功的AXIS例子(2431)
  • 3. 命令行创建ODBC数据源(1545)
  • 4. struts启动的一个错误!(1265)
  • 5. hibernate调用存储过程例子(1007)

评论排行榜

  • 1. JS实现文本框输入提供选择框的提示功能-1(7)
  • 2. 第一次做成功的AXIS例子(5)
  • 3. struts启动的一个错误!(4)
  • 4. 转:如何在JAVA中使用日期 (0)
  • 5. 命令行创建ODBC数据源(0)

View Post

Hibernate Gossip: 樂觀鎖定(Optimistic locking)

悲觀鎖定假定任何時刻存取資料時,都可能有另一個客戶也正在存取同一筆資料,因而對資料採取了資料庫層次的鎖定狀態,在鎖定的時間內其他的客戶不能對資料進行存取,對於單機或小系統而言,這並不成問題,然而如果是在網路上的系統,同時間會有許多連線,如果每一次讀取資料都造成鎖定,其後繼的存取就必須等待,這將造成效能上的問題,造成後繼使用者的長時間等待。

樂觀鎖定(Optimistic locking)則樂觀的認為資料的存取很少發生同時存取的問題,因而不作資料庫層次上的鎖定,為了維護正確的資料,樂觀鎖定使用應用程式上的邏輯實現版本控制的解決。

在不實行悲觀鎖定策略的情況下,資料不一致的情況一但發生,有幾個解決的方法,一種是先更新為主,一種是後更新的為主,比較複雜的就是檢查發生變動的資料來實現,或是檢查所有屬性來實現樂觀鎖定。

Hibernate中透過版本號檢查來實現後更新為主,這也是Hibernate所推薦的方式,在資料庫中加入一個version欄位記錄,在讀取資料時連同版本號一同讀取,並在更新資料時比對版本號與資料庫中的版本號,如果等於資料庫中的版本號則予以更新,並遞增版本號,如果小於資料庫中的版本號就丟出例外。

實際來透過範例瞭解Hibernate的樂觀鎖定如何實現,首先在資料庫中新增一個表格:

CREATE   TABLE   user  (
    id 
INT ( 11 )  NOT   NULL  auto_increment  PRIMARY   KEY ,
    version 
INT ,
    name 
VARCHAR ( 100 )  NOT   NULL   default   '' ,
    age 
INT
);


這個user表格中的version用來記錄版本號,以供Hibernate實現樂觀鎖定,接著設計User類別,當中必須包括version屬性:

 

  • User.java
package onlyfun.caterpillar;

public class User {
private Integer id;
private Integer version; // 增加版本屬性
private String name;
private Integer age;

public User() {
}

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

public Integer getVersion() {
return version;
}

public void setVersion(Integer version) {
this.version = version;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Integer getAge() {
return age;
}

public void setAge(Integer age) {
this.age = age;
}
}


在映射文件的定義方面,則如下所示:
  • User.hbm.xml
<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>

<class name="onlyfun.caterpillar.User"
table="user"
optimistic-lock="version">

<id name="id" column="id" type="java.lang.Integer">
<generator class="native"/>
</id>

<version name="version"
column="version"
type="java.lang.Integer"/>

<property name="name" column="name" type="java.lang.String"/>

<property name="age" column="age" type="java.lang.Integer"/>

</class>

</hibernate-mapping>


注意<version>標籤必須出現在<id>標籤之後,接著您可以試著在資料庫中新增資料,例如:

User user = new User();
user.setName("caterpillar");
user.setAge(new Integer(30));
Session session = sessionFactory.openSession();
Transaction tx =  session.beginTransaction();
session.save(user);
tx.commit();
session.close();


您可以檢視資料庫中的資料,每一次對同一筆資料進行更新,version欄位的內容都會自動更新,接著來作個實驗,直接以範例說明:

// 有使用1者開啟了一個session1
Session session1 = sessionFactory.openSession();
// 在這之後,馬上有另一個使用者2開啟了session2
Session session2 = sessionFactory.openSession();
       
Integer id = new Integer(1);

// 使用者1查詢資料       
User userV1 = (User) session1.load(User.class, id);
// 使用者2查詢同一筆資料
User userV2 = (User) session2.load(User.class, id);

// 此時兩個版本號是相同的
System.out.println(" v1 v2 "
                + userV1.getVersion().intValue() + " "
                + userV2.getVersion().intValue());
       
Transaction tx1 = session1.beginTransaction();
Transaction tx2 = session2.beginTransaction();

// 使用者1更新資料       
userV1.setAge(new Integer(31));
tx1.commit();

// 此時由於資料更新,資料庫中的版本號遞增了
// 兩筆資料版本號不一樣了
System.out.println(" v1 v2 "
                + userV1.getVersion().intValue() + " "
                + userV2.getVersion().intValue());
       
// userV2 的 age 資料還是舊的
// 資料更新
userV2.setName("justin");
// 因版本號比資料庫中的舊
// 送出更新資料會失敗,丟出StableObjectStateException例外
tx2.commit();
       
session1.close();
session2.close();


運行以下的程式片段,會出現以下的結果:

Hibernate: select user0_.id as id0_, user0_.version as version0_0_, user0_.name as name0_0_, user0_.age as age0_0_ from user user0_ where user0_.id=?
Hibernate: select user0_.id as id0_, user0_.version as version0_0_, user0_.name as name0_0_, user0_.age as age0_0_ from user user0_ where user0_.id=?
 v1 v2 0 0
Hibernate: update user set version=?, name=?, age=? where id=? and version=?
 v1 v2 1 0
Hibernate: update user set version=?, name=?, age=? where id=? and version=?
16:11:43,187 ERROR AbstractFlushingEventListener:277 - Could not synchronize database state with session
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [onlyfun.caterpillar.User#1]
    at org.hibernate.persister.entity.BasicEntityPersister.check(BasicEntityPersister.java:1441)


由於新的版本號是1,而userV2的版本號還是0,因此更新失敗丟出StableObjectStateException,您可以捕捉這個例外作善後處理,例如在處理中重新讀取資料庫中的資料,同時將目前的資料與資料庫中的資料秀出來,讓使用者有機會比對不一致的資料,以決定要變更的部份,或者您可以設計程式自動讀取新的資料,並比對真正要更新的資料,這一切可以在背景執行,而不用讓您的使用者知道。

要注意的是,由於樂觀鎖定是使用系統中的程式來控制,而不是使用資料庫中的鎖定機制,因而如果有人特意自行更新版本訊息來越過檢查,則鎖定機制就會無效,例如在上例中自行更改userV2的version屬性,使之與資料庫中的版本號相同的話就不會有錯誤,像這樣版本號被更改,或是由於資料是由外部系統而來,因而版本資訊不受控制時,鎖定機制將會有問題,設計時必須注意。


from : http://caterpillar.onlyfun.net/Gossip/HibernateGossip/HibernateGossip.html

posted on 2007-01-17 01:29 young 阅读(554) 评论(0)  编辑  收藏 所属分类: java

新用户注册  刷新评论列表  

只有注册用户登录后才能发表评论。


网站导航:
博客园   IT新闻   Chat2DB   C++博客   博问   管理
相关文章:
  • Hibernate Gossip: 樂觀鎖定(Optimistic locking)
  • 转:如何在JAVA中使用日期
  • Jakarta Commons:巧用类和组件1 (3)
  • Jakarta Commons:巧用类和组件1 (2)
  • Jakarta Commons:巧用类和组件1 (1)
  • Struts VS Turbine [转]
  • JDBC数据库连接池
 
 
Powered by:
BlogJava
Copyright © young