jinfeng_wang

G-G-S,D-D-U!

BlogJava 首页 新随笔 联系 聚合 管理
  400 Posts :: 0 Stories :: 296 Comments :: 0 Trackbacks

5.2 Working with application transactions

In our CaveatEmptor application, both the user who posted a comment and any system administrator can open an Edit Comment screen to delete or edit the text of a comment. Suppose two different administrators open the edit screen to view the same comment simultaneously. Both edit the comment text and submit their changes. At this point, we have three ways to handle the concurrent attempts to

write to the database:

Last commit wins—Both updates succeed, and the second update overwrites the changes of the first. No error message is shown.

First commit wins—The first modification is persisted, and the user submitting the second change receives an error message. The user must restart the business process by retrieving the updated comment. This option is often called optimistic locking.

        Merge conflicting updates—The first modification is persisted, and the second modification may be applied selectively by the user.

在我们的CavertEmptor中,用户和系统管理员都可以打开“编辑cooment”功能,删除或者编辑评论。假设同时有两个管理员对同一个评论打开编辑功能,他们都对评论进行编辑然后提交。这是,我们发现可能有三种方式对此并发操作进行处理、写入数据库:

   后者提交获胜-两次更新都成功,但是第二次更新将会覆盖第一次的更新,不显示任何错误。

   前者提交获胜-第一个提交者成功,更新数据库,后一个提交失败,并返回错误信息。用户必须重新开始整个业务过程,取得被更新的评论。者就是常说的“乐观锁”。

   合并更新冲突-第一个更新被保存,而第二个更新则由用户选择是否保存。

 

The first option, last commit wins, is problematic; the second user overwrites the changes of the first user without seeing the changes made by the first user or even knowing that they existed. In our example, this probably wouldn’t matter, but it would be unacceptable for some other kinds of data. The second and third options are usually acceptable for most kinds of data. From our point of view, the third option is just a variation of the second—instead of showing an error message, we show the message and then allow the user to manually merge changes. There is no single best solution. You must investigate your own business requirements to decide among these three options.

上面的第一个方案是有问题的:第二个用户在不知道改变、甚至不知道第一个用户已经操作的情况下,直接重写了数据库。在我们的例子中,也许是没关系的,但是对于某些应用是不可接受的。第二个和第三个方案对于绝大部分数据是可以结束的。按照我们的观点,第三个是第二个的变种,它不是显式错误信息,而是给用户进行选择,允许用户手工合并对数据的修改。这里并没有一个最完美的解决方案。你必须根据你自己项目的需要自行选择方案。

 

The first option happens by default if you don’t do anything special in your applicationOn the other hand, Hibernate can help you implement the second and third strategies, using managed versioning for optimistic locking.

如果在你的项目中不采取任何措施,那么会默认使用第一个方案。但是,hibernate可以通过使用对“乐观锁”使用“管理版本”,帮助你实现第二个或第三个方案。

 

Managed versioning relies on either a version number that is incremented or a timestamp that is updated to the current time, every time an object is modified. For Hibernate managed versioning, we must add a new property to our Comment class and map it as a version number using the <version> tag. First, let’s look at the changes to the Comment class:

public class Comment {

...

private int version;

...

void setVersion(int version) {

this.version = version;

}

int getVersion() {

return version;

}

}

“管理版本”使用版本号或者时间戳对数据进行标记,每次数据在更新的时候,它都会被更新。对于hibernate,我们必须给Comment类,添加新的属性,然后使用<version>标签对其进行映射。首先让我们来看一下Comment类的改变:

public class Comment {

...

private int version;

...

void setVersion(int version) {

this.version = version;

}

int getVersion() {

return version;

}

}

 

You can also use a public scope for the setter and getter methods. The <version> property mapping must come immediately after the identifier property mapping in the mapping file for the Comment class:

<class name="Comment" table="COMMENTS">

<id ...

<version name="version" column="VERSION"/>

...

</>

你可以使用publicsettergetter方法,这里的<version>映射的定义必须紧跟在映射文件中comment类的id后面。

<class name="Comment" table="COMMENTS">

<id ...

<version name="version" column="VERSION"/>

...

</>

 

You don’t need to set the value of the version or timestamp property yourself; Hibernate will initialize the value when you first save a Comment, and increment or reset it whenever the object is modified. Whenever Hibernate updates a comment, it uses the version column in the SQLWHERE clause:

update COMMENTS set COMMENT_TEXT='New comment text', VERSION=3

where COMMENT_ID=123 and VERSION=2

你无需自己手工去修改这里的版本号或者时间戳,hibernate将会在你保存Commment的时候对其初始化,然后在对象每次被更新的时候即使更新其版本号和时间戳。无论hibernate何时更新comment,它都会在SQL语句的where后面加上version列:

update COMMENTS set COMMENT_TEXT='New comment text', VERSION=3

where COMMENT_ID=123 and VERSION=2

 

If another application transaction would have updated the same item since it was read by the current application transaction, the VERSION column would not contain the value 2, and the row would not be updated. Hibernate would check the row count returned by the JDBC driver—which in this case would be the number of rows updated, zero—and throw a StaleObjectStateException. Using this exception, we might show the user of the second application transaction an error message (“You have been working with stale data because another user modified it!”) and let the first commit win. Alternatively, we could catch the exception and show the second user a new screen, allowing the user to manually merge changes between the two versions.

如果某个事务已经更新了某个数据,而另外一个事务也准备更新此数据,但是当时它取得数据的版本号是2,而此时由于该数据已经被更新过,新版本号是3,因此将无法更新数据库中的任何的数据。这时候hibernate将会检查jdbc的返回行数-如果未有任何数据行被更新,则返回0-因此将会抛出StaleObjectStateException异常。

 

Using this exception, we might show the user of the second application transaction an error message (“You have been working with stale data because another user modified it!”) and let the first commit win. Alternatively, we could catch the exception and show the second user a new screen, allowing the user to manually merge changes between the two versions.

使用此异常,就可以给第二个应用事务的用户显式错误信息(你正使用的数据已经被其他人更新了),让第一个提交者获胜。当然,你也可以捕捉异常,然后给第二个用户一个新的平面,允许它手工合并这两个版本的数据。
posted on 2005-04-07 16:10 jinfeng_wang 阅读(7490) 评论(1)  编辑  收藏 所属分类: hibernate

评论

# re: hibernate transaction theory(2) 2006-04-18 19:41 BVBV
当你想起距离,你想起,我们是不朽的[url=http://www.v815.net]wow gold[/url],你想起它们是从我们出发的,所有的距离,都是从我们出发的,没有一个死去,没有一个被忘记[url=http://www.xinjizhen.com.cn]wow gold[/url]世界上各地都有母兽,仰天躺着,想起海.当你想起距离,你想起,我们是不朽的<a href="http://www.v815.net">wow gold</a>,你想起它们是从我们出发的,所有的距离,都是从我们出发的,没有一个死去,没有一个被忘记<a href="http://www.xinjizhen.com.cn">wow gold</a><br>世界上各地都有母兽,仰天躺着,想起海.
  回复  更多评论
  


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


网站导航: