J2EE事务并发控制策略总结(3)(转载)
2009-04-30 09:30
459 查看
下面就分别以JDBC和Hibernate来总结一下:
JDBC中使用悲观锁:在JDBC中使用悲观锁,需要使用select for update语句,假如我们系统中有一个Account的类,我们可以采用如下的方式来进行:
Select * from Account where ...(where condition).. for update.
当使用了for update语句后,每次在读取或者加载一条记录的时候,都会锁住被加载的记录,那么当其他事务如果要更新或者是加载此条记录就会因为不能获得锁而阻塞,这样就避免了不可重复读以及脏读的问题,但是其他事务还是可以插入和删除记录,这样也许同一个事务中的两次读取会得到不同的结果集,但是这不是悲观锁锁造成的问题,这是我们数据库隔离级别所造成的问题。
最后还需要注意的一点就是每个冲突的事务中,我们必须使用select for update 语句来进行数据库的访问,如果一些事务没有使用select for update语句,那么就会很容易造成错误,这也是采用JDBC进行悲观控制的缺点。
Hibernate中使用悲观锁:相比于JDBC使用悲观锁来说,在Hibernate中使用悲观锁将会容易很多,因为Hibernate有API让我们来调用,从而避免直接写SQL语句。下面就Hibernate使用悲观锁做一总结:
首先先要明确一下Hibernate中支持悲观锁的两种模式LockMode.UPGRADE以LockMode.UPGRADE_NO_WAIT.(PS:在JPA中,对应的锁模式是LockModeType.Read,这与Hibernate是不一样的呵呵)
假如我们系统中有一个Account的类,那么具体的操作可以像这样:
.......
session.lock(account, LockMode.UPGRADE);
......
或者也可以采用如下方式来加载对象:
session.get(Account.class,identity,LockMode.UPGRADE).
这样以来当加载对象时,hibernate内部会生成相应的select for update语句来加载对象,从而锁定对应的记录,避免其它事务并发更新。
以上两种策略都是针对同一个事务而言的,如果我们要实现跨多个事务的并发控制就要采用其它两种并发控制策略了,下面做一总结:
C++与java是两种完全不同风格的东西,C++是由程序员创造的,由程序员完善的,然后才出的标准的,也就是说C++的标准完全落后与C++的发展。java恰好相反,它是先有标准(可能还没有实现),然后后有的实现,而且它是由公司主导开发的,虽然现在开源了,但是标准并不是谁都能定的。这就造就了C++是百花齐放,博大精深,很少有人敢说自己C++很厉害。java却是另外的一种感觉,一切都规定好了,你只需要按照规定去做,符合标准才可以的。所以C++是那种既可以做的堂堂正正,博大精深(比如标准库),又可以实现的匪夷所思,天马行空(写 Boost库的人太牛了)。java不行,java要求如此只能如此,不能越雷池一步。
JDBC中使用悲观锁:在JDBC中使用悲观锁,需要使用select for update语句,假如我们系统中有一个Account的类,我们可以采用如下的方式来进行:
Select * from Account where ...(where condition).. for update.
当使用了for update语句后,每次在读取或者加载一条记录的时候,都会锁住被加载的记录,那么当其他事务如果要更新或者是加载此条记录就会因为不能获得锁而阻塞,这样就避免了不可重复读以及脏读的问题,但是其他事务还是可以插入和删除记录,这样也许同一个事务中的两次读取会得到不同的结果集,但是这不是悲观锁锁造成的问题,这是我们数据库隔离级别所造成的问题。
最后还需要注意的一点就是每个冲突的事务中,我们必须使用select for update 语句来进行数据库的访问,如果一些事务没有使用select for update语句,那么就会很容易造成错误,这也是采用JDBC进行悲观控制的缺点。
Hibernate中使用悲观锁:相比于JDBC使用悲观锁来说,在Hibernate中使用悲观锁将会容易很多,因为Hibernate有API让我们来调用,从而避免直接写SQL语句。下面就Hibernate使用悲观锁做一总结:
首先先要明确一下Hibernate中支持悲观锁的两种模式LockMode.UPGRADE以LockMode.UPGRADE_NO_WAIT.(PS:在JPA中,对应的锁模式是LockModeType.Read,这与Hibernate是不一样的呵呵)
假如我们系统中有一个Account的类,那么具体的操作可以像这样:
.......
session.lock(account, LockMode.UPGRADE);
......
或者也可以采用如下方式来加载对象:
session.get(Account.class,identity,LockMode.UPGRADE).
这样以来当加载对象时,hibernate内部会生成相应的select for update语句来加载对象,从而锁定对应的记录,避免其它事务并发更新。
以上两种策略都是针对同一个事务而言的,如果我们要实现跨多个事务的并发控制就要采用其它两种并发控制策略了,下面做一总结:
C++与java是两种完全不同风格的东西,C++是由程序员创造的,由程序员完善的,然后才出的标准的,也就是说C++的标准完全落后与C++的发展。java恰好相反,它是先有标准(可能还没有实现),然后后有的实现,而且它是由公司主导开发的,虽然现在开源了,但是标准并不是谁都能定的。这就造就了C++是百花齐放,博大精深,很少有人敢说自己C++很厉害。java却是另外的一种感觉,一切都规定好了,你只需要按照规定去做,符合标准才可以的。所以C++是那种既可以做的堂堂正正,博大精深(比如标准库),又可以实现的匪夷所思,天马行空(写 Boost库的人太牛了)。java不行,java要求如此只能如此,不能越雷池一步。
相关文章推荐
- J2EE事务并发控制策略总结
- J2EE事务并发控制策略总结
- J2EE事务并发控制策略总结
- J2EE事务并发控制策略总结
- J2EE事务并发控制策略总结
- J2EE事务并发控制策略总结
- J2EE并发策略控制总结[zz]
- j2ee 并发控制策略总结
- JDBC第四章知识点总结——JDBC高级特性2--事务,并发控制,行集
- JDBC第四章知识点总结——JDBC高级特性2--事务,并发控制,行集
- 事务策略: 高并发策略
- .net中的4种事务总结[转载]
- 数据库并发事务控制四:postgresql数据库的锁机制
- hibernate之控制并发访问(ANSI事务隔离性级别)
- Linux内核开发之并发控制(实例总结篇)
- Hibernate事务和并发控制
- LINQ : 在LINQ TO SQL中使用事务和控制并发
- LINQ体验(10)——LINQ to SQL语句之开放式并发控制和事务
- LINQ体验(10)——LINQ to SQL语句之开放式并发控制和事务
- 深入理解Mysql——锁、事务与并发控制