Spring 注解@Transactional readOnly=true

来源:互联网 发布:js arguments 回调函数 编辑:程序博客网 时间:2024/06/06 12:42

Spring注解@Transactional readOnly=true

Spring  Service类中的注解@TransactionalreadOnly=true的作用。居然想都没有想就说是注解事务控制,然后给他扯了一通数据库的隔离级别,什么readuncommit之类的,说readOnly是隔离级别最低的,在spring查询方法里用,性能最高。 

ps:之前的项目多数基于xml,亲自用annotation的机会很少,都是小弟们在实战。 

示例: 

Java  

1. @Component("channelService")  

2. @Transactional(readOnly = true)  

3. public class ChannelServiceImpl implements IChannelService {  

4.     @Resource(name = "productService")  

5.     private IProductService productService;  

6.   

7.     /** 

8.       * 根据道名字查询频道。没有就返回NULL 

9.      * 

10.     * @param name 道名称不能空。 

11.     * @return (假设频道名称是加了唯一束的,否可能果不止一条致异常) 

12.     */  

13.    @MethodCache(expire = 3600)  

14.    @Transactional(readOnly = true)  

15.    public ChannelVO getChannelByName(String name) {  

16.        if (name == null || "".equals(name.trim())) {  

17.            throw new IllegalArgumentException("name=" + name);  

18.        }  

19.        ShopChannels channel = (ShopChannels) channelDao.createCriteria()  

20.                .add(Restrictions.eq("name", name))  

21.                .uniqueResult();  

22.        if (channel == null) {  

23.            return new ChannelVO();  

24.        }  

25.        ChannelVO vo = new ChannelVO();  

26.        DozerMapper.getInstance().map(channel, vo);  

27.         //增加对应商品分id 只取第一个分  

28.        Set<ProductClass> listCates = channel.getProductClasses();  

29.        if (listCates != null && !listCates.isEmpty()) {  

30.            vo.setProductClass("" + listCates.iterator().next().getSid());  

31.        }  

32.        List<Integer> list = new ArrayList<Integer>();  

33.        Iterator<ProductClass> iterator = listCates.iterator();  

34.        while (iterator.hasNext()) {  

35.            ProductClass productClass = iterator.next();  

36.            list.add(productClass.getSid());  

37.        }  

38.        vo.setAllProductClass(list);  

39.        return vo;  

40.}  

41.}  



数据隔离相关内容 

在一个应用中,依据事务的隔离级别将会有三种情况发生。 
  ◆脏读dirtyread):当一个事务读取另一个事务尚未提交的修改时,产生脏读。 
  ◆ 不可重复non-repeatableread):同一查询在同一事务中多次进行,由于其他提交事务所做的修改或删除,每次返回不同的结果集,此时发生非重复读。: 
  ◆ 幻像phantomread):同一查询在同一事务中多次进行,由于其他提交事务所做的插入操作,每次返回不同的结果集,此时发生幻像读。 

1.Read Committed: 
假设A事务对正在读取数据Data放置了共享锁,那么Data不能被其它事务改写,所以当B事务对Data进行读取时总和A读取的Data数据是一致的,所以避免了脏读。由于在A没有提交之前可以对Data进行改写,那么B读取到的某个值可能会在其读取后被A更改从而导致了该值不能被重复取得;或者当B再次用相同的where字句时得到了和前一次不一样数据的结果集,也就是幻像数据。 

2.Read Uncommitted 
假设A事务即不发布共享锁,也不接受独占锁,那么并发的B或者其它事务可以改写A事务读取的数据,那么并发的C事务读取到的数据的状态和A的或者B的数据都可能不一致,那么。脏读、不可重复读、幻象数据都可能存在。 

3.Repeatable Read 
(注意MSDN原文中的第一句话:在查询中使用的所有数据上放置锁,所以不存在脏读的情况)。 
假设A事务对读取的所有数据Data放置了锁,以阻止其它事务对Data的更改,在A没有提交之前,新的并发事务读取到的数据如果存在于Data中,那么该数据的状态和A事务中的数据是一致的,从而避免了不可重复的读取。但在A事务没有结束之前,B事务可以插入新记录到Data所在的表中,那么其它事务再次用相同的where字句查询时,得到的结果数可能上一次的不一致,也就是幻像数据。 

4.Serializable 
在数据表上放置了排他锁,以防止在事务完成之前由其他用户更新行或向数据集中插入行,这是最严格的锁。它防止了脏读、不可重复读取和幻象数据。 

以下是对照表: 

 


一般的应用作隔离级别时,往往采用(2),(3)两种,(1),(4)两种前者轻后者重,但是Hibernate为了提高performance和scalability,在数据库一层中采用的是(2)的隔离级别,然后在程序中进行控制,从而实现了(3)的隔离级别,因此提高了企业应用的事务处理效率。当然Hibernate对于数据库一层的隔离级别也可以显示指定。Hibernate在程序中的控制方法有:version number,timestamp,对于遗留database也有optimistic-lock,而version number有时不能解决特殊的事务并发引起来的(3)问题,那么就需要针对特殊情况进行细粒度的事务控制,可以看一下LOCKMODE。 

回家反思存策略 

回家一想,不对,应该不完全是隔离级别的东西,自已可能肯定搞错了,于是赶紧翻看hibernate3.3reference.果然没说对。应该是二级缓存的策略问题。但不知为什么reference中没有讲到query cacheannotation的东西,只是一页带过。提高性能中二级缓存策略倒是讲了不少。 
备忘: 

Chapter 19. Improving performance 
19.2.
The SecondLevel Cache 
19.2.1. Cache mappings 
The <cache> element of a class or collection mapping has the followingform: 

Java  

1. <cache   

2.     usage="transactional|read-write|nonstrict-read-write|read-only"    

3.     region="RegionName"                                                

4.     include="all|non-lazy"                                             

5. />  

usage(required) specifies the caching strategy: transactional, read-write,nonstrict- 
read-write or read-only 
region (optional: defaults to the class or collection role name): specifies thename of the 
second level cache region 
include (optional: defaults to all) non-lazy: specifies that properties of theentity mapped 
with lazy="true" cannot be cached when attribute-level lazy fetchingis enabled 
Alternatively, you  can  specify  <class-cache> and <collection-cache>  elements  in 
hibernate.cfg.xml. 
The usage attribute specifies a cache concurrency strategy. 

直接要的看各种策略明: 

Strategy: read only 
If your application needs to read, but not modify, instances of a persistentclass, a read-only 
cache can be used. This is the simplest and optimal performing strategy. It iseven safe for use 
in a cluster. 
如果用只需要查询,不需要修改,那么read-only存将使用,是最简单、最理想的性能策略,它在集群境下也是安全的。 

Strategy:read/write 
If  the  application  needs  to  update  data,a  read-write  cache  might  be  appropriate.This cache  strategy  should  never  be  used if  serializable  transaction  isolation  level  isrequired.  
如果用需要修改,read-writecache是最合适的。个cache策略永不会使用,如果数据隔离级别是可序列化serializable的。里看和隔离级别又有点关系。 

Strategy: nonstrict  read/write 
If the application only occasionally needs to update data (i.e. if it isextremely unlikely that two 
transactions would try to update the same item simultaneously), and stricttransaction isolation 
is not required, a nonstrict-read-write cache might be appropriate. If the cacheis used in a 
JTA environment, you must specify hibernate.transaction.manager_lookup_class.In other 
environments, you should ensure that the transaction is completed whenSession.close() or 
Session.disconnect() is called. 
如果仅仅的修改数据,并不需要格的数据隔离级别Nonstrict-read-write存是最合适的。 

Strategy: transactional 
The transactional cache strategy provides support for fully  transactionalcache providers such 
as JBoss TreeCache. Such a cachecan only be used in a JTA environment and you must specify 
hibernate.transaction.manager_lookup_class. 
The transactional cache strategy提供完全的事务缓存机制,例如JBossTreeCache.这样存只能用在JTA境中,你也必需指定相关 

Important 
None of the cache providers support all of the cache concurrencystrategies. 
The following table shows which providers are compatible with which concurrencystrategies. 

 


@Transactional 

再想想,还是不对,hibernate中并没有提到最开始annotation的东西,于是继续纠结Spring3.0 Reference Documentation。 

Using @Transactional 
In addition to the XML-based declarative approach to transaction configuration,you can use an 
annotation-based approach. Declaring transaction semantics directly in the Javasource code puts the declarations much closer to the affected code. There isnot much danger of undue coupling, because code that is meant to be usedtransactionally is almost always deployed that way anyway. 
annotation控制,代替xml的。其它废话少翻。 
You can place the @Transactional annotation before an interface definition, amethod on an Interface, a class definition, or a public method on a class.However, the mere presence of the 
@Transactional annotation is not enough to activate the transactional behavior.The 
@Transactional annotation is simply metadata that can be consumed by someruntime infrastructure that is @Transactional-aware and that can use themetadata to configure the appropriate beans with transactional behavior. In thepreceding example, the <tx:annotation-driven/> element switches 
onthetransactionalbehavior. 

Java  

1. //文档例子:  

2. @Transactional(readOnly = true)  

3. public class DefaultFooService implements FooService {  

4. public Foo getFoo(String fooName) {  

5. // do something  

6. }  

7. // these settings have precedence for this method  

8. @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)  

9. public void updateFoo(Foo foo) {  

10.// do something  

11.}  

12.}  



@Transactional  settings 
The @Transactional annotation is metadata that specifies that an interface,class, or method must have transactional semantics; for example, “start a brandnew read-only transaction when this method is invoked。 
@Transactional注解是规定接口,类或者方法必需应用事务的元数据语法。 

看看spring默认的设置: 

Java  

1. //认传播机制:PROPAGATION_REQUIRED  

2. * Propagation setting is PROPAGATION_REQUIRED.  

3. //隔离级别ISOLATION_DEFAULT  

4. * Isolation level is ISOLATION_DEFAULT.  

5. //read/write.到此知道查询readOnly的作用。  

6. * Transaction is read/write.  

7.  //时时间取决于事,也有可能没有,如果事不支持。  

8. * Transaction timeout defaults to the default timeout of the underlying transaction system, or to none if time outs are not supported.  

9. //任何的RuntimeExcetipn将触,任何的checkedException不触  

10.* Any RuntimeException triggers rollback,and any checkedException does not.  



明细配置: 

 


 

 

0 0
原创粉丝点击