??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲日日夜夜,成人久久网站,欧美精品一区二区高清在线观看http://www.aygfsteel.com/yuyee/category/46759.htmlzh-cnWed, 03 Nov 2010 10:26:20 GMTWed, 03 Nov 2010 10:26:20 GMT60嵌套事务http://www.aygfsteel.com/yuyee/archive/2010/11/03/336885.htmlTue, 02 Nov 2010 16:11:00 GMThttp://www.aygfsteel.com/yuyee/archive/2010/11/03/336885.html在所有?spring 的应用中, 声明式事务管理可能是使用率最高的功能? 但是, 从我观察到的情况? l大多数人ƈ不能深刻理解事务声明中不同事务传播属性配|的的含? 让我们来看一下TransactionDefinition 接口中的定义 Q在 spring 中一共定义了六种事务传播属? 如果你觉得看h不够直观, 那么我来转脓一个满大街都有的翻?/span> 
PROPAGATION_REQUIRED -- 支持当前事务Q如果当前没有事务,新Z个事务。这是最常见的选择?nbsp;
PROPAGATION_SUPPORTS 
-- 支持当前事务Q如果当前没有事务,׃非事务方式执行?nbsp;
PROPAGATION_MANDATORY 
-- 支持当前事务Q如果当前没有事务,抛出异常?nbsp;
PROPAGATION_REQUIRES_NEW 
-- 新徏事务Q如果当前存在事务,把当前事务挂赗?nbsp;
PROPAGATION_NOT_SUPPORTED 
-- 以非事务方式执行操作Q如果当前存在事务,把当前事务挂v?nbsp;
PROPAGATION_NEVER 
-- 以非事务方式执行Q如果当前存在事务,则抛出异常?nbsp;
PROPAGATION_NESTED 
-- 如果当前存在事务Q则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIREDcM的操作?nbsp;
前六个策略类gEJB CMTQ第七个QPROPAGATION_NESTEDQ是Spring所提供的一个特D变量?nbsp;
它要求事务管理器或者用JDBC 
3.0 Savepoint API提供嵌套事务行ؓQ如Spring的DataSourceTransactionManagerQ?nbsp;

在我所见过的误解中, 最常见的是下面q种: 
假如有两个业务接?nbsp;ServiceA ?nbsp;ServiceB, 其中 ServiceA 中有一个方法实现如?nbsp;
/** 
* 事务属性配|ؓ PROPAGATION_REQUIRED 
*/
 
void methodA() 
// 调用 ServiceB 的方?nbsp;
ServiceB.methodB(); 
}
 
那么如果 ServiceB ?nbsp;methodB  如果配置了事? 必配|ؓ PROPAGATION_NESTED 


q种x可能害了不少? 认ؓ Service 之间应该避免互相调用, 其实Ҏ不用担心q点QPROPAGATION_REQUIRED 已经说得很明? 
如果当前U程中已l存在事? Ҏ调用会加入此事务, 果当前没有事务,新Z个事? 所?ServiceB#methodB() 的事务只要遵循最普通的规则配置?PROPAGATION_REQUIRED 卛_, 如果 ServiceB#methodB (我们UC为内部事? Z文打下基) 抛了异常, 那么 ServiceA#methodA(我们UC为外部事? 如果没有Ҏ配置此异常时事务提交 (?+MyCheckedException的用?, 那么整个事务是一定要 rollback ? 什?Service 只能?Dao 之类的言论纯属无E之? spring 只负责配|了事务属性方法的拦截, 它怎么知道你这个方法是?Service q是 Dao ?? 

最Ҏ弄؜淆的其实?PROPAGATION_REQUIRES_NEW ?PROPAGATION_NESTED, 那么q两U方式又有何区别? 我简单的译一?Juergen Hoeller 的话 : 
PROPAGATION_REQUIRES_NEW 启动一个新? 不依赖于环境?"内部" 事务. q个事务被完全 commited ?rolled back 而不依赖于外部事? 它拥有自q隔离范围, 自己的锁, {等. 当内部事务开始执行时, 外部事务被挂v, 内务事务l束? 外部事务l执? 

    另一斚w, PROPAGATION_NESTED 开始一?"嵌套? 事务,  它是已经存在事务的一个真正的子事? 潜套事务开始执行时,  它将取得一?savepoint. 如果q个嵌套事务p|, 我们回滚到?savepoint. 潜套事务是外部事务的一部分, 只有外部事务l束后它才会被提? 

    由此可见, PROPAGATION_REQUIRES_NEW ?PROPAGATION_NESTED 的最大区别在? PROPAGATION_REQUIRES_NEW 完全是一个新的事? ?PROPAGATION_NESTED 则是外部事务的子事务, 如果外部事务 commit, 潜套事务也会?commit, q个规则同样适用?roll back.

 那么外部事务如何利用嵌套事务?savepoint Ҏ呢, 我们用代码来说话

 

ServiceA {       
    
/**  
     * 事务属性配|ؓ PROPAGATION_REQUIRED  
     
*/
  
    
void methodA() {   
        ServiceB.methodB();    }
   
 }
     
ServiceB 
{      
    
/**  
     * 事务属性配|ؓ PROPAGATION_REQUIRES_NEW  
     
*/
    
    
void methodB() {   
    }
         
}
   

q种情况? 因ؓ ServiceB#methodB 的事务属性ؓ PROPAGATION_REQUIRES_NEW, 所以两者不会发生Q何关p? ServiceA#methodA ?ServiceB#methodB 不会因ؓҎ的执行情况而媄响事务的l果, 因ؓ它们Ҏ是两个事务, ?ServiceB#methodB 执行?ServiceA#methodA 的事务已l挂起了 (关于事务挂v的内容已l超Z本文的讨? 有时间我会再写一些挂L文章) . 

ServiceA {      
    
/**  
     * 事务属性配|ؓ PROPAGATION_REQUIRED  
     
*/
  
    
void methodA() {   
        ServiceB.methodB();   
    }
   
}
     
ServiceB 
{         
    
/**  
     * 事务属性配|ؓ PROPAGATION_NESTED  
     
*/
    
    
void methodB() {   
    }
         
}
 

ServiceB#methodB 如果 rollback, 那么内部事务(?ServiceB#methodB) 回滚到它执行前?SavePoint(注意, q是本文中第一ơ提到它, 潜套事务中最核心的概?, 而外部事??ServiceA#methodA) 可以有以下两U处理方? 
1. 改写 ServiceA 如下 

ServiceA {      
    
/**  
     * 事务属性配|ؓ PROPAGATION_REQUIRED  
     
*/
  
    
void methodA() {   
        
try {   
            ServiceB.methodB();   
        }
 catch (SomeException) {   
            
// 执行其他业务, ?nbsp;ServiceC.methodC();   
        }
   
    }
    
}
  

q种方式也是潜套事务最有h值的地方, 它vC分支执行的效? 如果 ServiceB.methodB p|, 那么执行 ServiceC.methodC(), ?ServiceB.methodB 已经回滚到它执行之前?SavePoint, 所以不会生脏数据(相当于此Ҏ从未执行q?, q种Ҏ可以用在某些特D的业务? ?PROPAGATION_REQUIRED ?PROPAGATION_REQUIRES_NEW 都没有办法做到这一? (题外?: 看到q种代码, g似曾相识, 惌v?prototype.js 中的 Try 函数 ) 

2. 代码不做M修改, 那么如果内部事务(?ServiceB#methodB) rollback, 那么首先 ServiceB.methodB 回滚到它执行之前?SavePoint(在Q何情况下都会如此), 外部事务(?ServiceA#methodA) 根据具体的配置军_自己?commit q是 rollback (+MyCheckedException). 
上面大致讲述了潜套事务的使用场景, 下面我们来看如何?spring 中?PROPAGATION_NESTED, 首先来看 AbstractPlatformTransactionManager 

JdbcTransactionObjectSupport 告诉我们必须要满两个条件才?createSavepoint : 
  
2. java.sql.Savepoint 必须存在, ?jdk 版本?1.4+ 
3. Connection.getMetaData().supportsSavepoints() 必须?true, ?jdbc drive 必须支持 JDBC 3.0 


保以上条g都满_, 你就可以试使用 PROPAGATION_NESTED ?



2010-11-03 00:11 发表评论
]]>
hibernate单知?/title><link>http://www.aygfsteel.com/yuyee/archive/2010/10/25/336047.html</link><dc:creator>羊</dc:creator><author>羊</author><pubDate>Sun, 24 Oct 2010 16:30:00 GMT</pubDate><guid>http://www.aygfsteel.com/yuyee/archive/2010/10/25/336047.html</guid><description><![CDATA[<p align="center"><font size="7" face="Calibri">Session接口几个基本操作</font> <br /> </p> <ul> <ul type="DISC"> <li><font size="6" face="Calibri">1.get()Ҏ:先确认该ID对应的数据是否存?<wbr>先经qsession~存,再二U缓?之后是数据库,<wbr>如果不存?q回null</font></li> <li><font size="6" face="Calibri">2.load()Ҏ:hibernate会默认你是存在的,<wbr>他会攑ֿ的用代理类在gq加载数?当用C的其他属性时,<wbr>׃跑去数据库中查询,如果不在,抛异?/font></li> <li><font size="6" face="Calibri">3.list()Ҏ:L据库d数据,填充~存,</font></li> <li><font size="6" face="Calibri">4.iterator()Ҏ:先去数据库select id from table,之后到缓存中查找,如果不存?出现N+1问题.</font></li> </ul> </ul> <p align="center"><font size="7" face="Calibri">~存</font> <br /> </p> <ul> <ul type="DISC"> <li><font size="6" face="Calibri">1.一U缓?sessionU缓?如果session关闭,<wbr>,清空,释放内存</font></li> </ul> </ul>  <br /> <ul> <ul type="DISC"> <li><font size="6" face="Calibri">2.二~存:SessionFactoryU别的全局~存Q?wbr>它底下可以用不同的~存cdQ比如ehcache?wbr>oscache{,需要设|hibernate.cache.<wbr>provider_class</font></li> <li><font size="6" face="Calibri">~存可以看成是个hastable,典型的空间换旉,<wbr>一般在d比高的情况下使用</font></li> </ul> </ul> <p align="center"><font size="7" face="Calibri">Hibernate中用二U缓?/font> <br /> </p> <ul> <ul type="DISC"> <li><font size="7" face="Calibri"><strong>Class的缓?/strong>  <br /> </font><font size="6" face="Calibri">对于一条记录,也就是一个PO来说Q是ҎID来找的,<wbr>~存的key是IDQvalue是POJO。无论listQ?wbr>loadq是iterateQ只要读Z个对象,都会填充~存?wbr>但是list不会使用~存Q?wbr>而iterate会先取数据库select id出来Q然后一个id一个id的loadQ如果在~存里面有,<wbr>׃~存取,没有的话去数据库load。假设是d~存Q?wbr>需要设|:  <br /> <cache usage=“read-write”/><~存q发{略></font></li> <li><font size="6" face="Calibri">使用二~存W三Ҏ件ehcache.jar来实?<wbr>在hibernate.cfg.xml中配|?/font></li> <li><font size="6" face="Calibri">如下?是我试TestDAO工程的hiberante.<wbr>cfg.xml配置</font></li> </ul> </ul> <p align="center"><font size="7" face="Calibri">Hiberante.cfg.xml</font></p> <p align="center"><font size="7" face="Calibri">ehcache.xml配置</font> <br /> </p> <ul> <ul type="DISC"> <li><font size="6" face="Calibri"><defaultCache  <br />         maxElementsInMemory=“10000” //在缓存区最大元?默认?0000Q?nbsp; <br />         eternal=“false”  //是否怹不超? <br />         timeToIdleSeconds=“120”  // Q缓存数据的钝化旉Q也是在一个元素消亡之前,<wbr>两次讉K旉的最大时间间隔? <br />         timeToLiveSeconds=“120” //<wbr>从创建后存活的最长时? <br />         overflowToDisk="true" //溢出到硬盘;  <br />         /> </font></li> </ul> </ul>  <br /> <ul> <ul type="DISC"> <li><font size="6" face="Calibri">每个存储的CLASS都要有这L配置,如果你没配置,<wbr>Hibernate会警告你,<wbr>然后使用~省的defaultCache</font></li> </ul> </ul> <p align="center"><font size="7" face="Calibri"><strong>查询~存</strong> </font> <br /> </p> <ul> <ul type="DISC"> <li><font size="5" face="Calibri">需要配|?lt;property name=<em>"hibernate.cache.use_<wbr>query_cache">true</property></em></font></li> <li><font size="5" face="Calibri">query.setCacheable(true);//<wbr>ȀzL询缓?nbsp; <br /> query.setCacheRegion(“<wbr>myCacheRegion”);//<wbr>指定要用的cacheRegion,如果不做,<wbr>会用标准的查询~存的配|?/font></li> <li><font size="5" face="Calibri">查询~存来说Q缓存的key是根据hql生成的sqlQ?wbr>再加上参敎ͼ分页{信?/font></li> <li><font size="5" face="Calibri"><strong><em>重点</em></strong><em>:</em>如果是list()方式的话Q?wbr>value在这里ƈ不是整个l果集,而是查询出来的一串ID.</font></li> <li><font size="5" face="Calibri">不管是listҎq是iterateҎQ第一ơ查询的时候,<wbr>它们的查询方式和它们qx的方式是一LQ?wbr>list执行一条sqlQiterate执行1+N条,<wbr>多出来的行ؓ是它们填充了~存?wbr>但是到同h件第二次查询的时候,<wbr>都和iterate的行Z样了Q?wbr>Ҏ~存的keyȝ存里面查CvalueQ?wbr>value是一串idQ?wbr>然后在到class的缓存里面去一个一个的load出来?/font></li> <li><font size="5" face="Calibri"><em>所以说,</em>查询~存需要打开相关cȝclass~存?wbr>list和iterateҎW一ơ执行的时候,<wbr>都是既填充查询缓存又填充class~存?q有一?<wbr>Class~存的时间一定要比查询缓存长,不然q是会出现N+<wbr>1问题</font></li> </ul> </ul> <p align="center"><font size="7" face="Calibri">~存与数据库同步</font> <br /> </p> <ul> <ul type="DISC"> <li><font size="5" face="Calibri">hibernate在一个地方维护每个表的最后更新时_<wbr>其实也就是放在上面org.hibernate.cache. UpdateTimestampsCache所指定的缓存配|里<wbr>面?nbsp;</font></li> </ul> </ul>  <br />  <br />  <br />  <br />  <br />  <br />  <br />  <br />  <br />  <br />  <br />  <br />  <br />  <br />  <br />  <br />  <br />  <br />  <br />  <br />  <br />  <br />  <br />  <br /> <ul> <ul type="DISC"> <li><font size="1" face="Calibri">  <br /> </font><font size="5" face="Calibri">当通过hibernate更新的时候,<wbr>hibernate会知道这ơ更新媄响了哪些表?wbr>然后它更新这些表的最后更新时间?wbr>每个~存都有一个生成时间和q个~存所查询的表Q?wbr>当hibernate查询一个缓存是否存在的时候,<wbr>如果~存存在Q它q要取出~存的生成时间和q个~存所查询的表Q?wbr>然后L找这些表的最后更新时_<wbr>如果有一个表在生成时间后更新q了Q那么这个缓存是无效的?nbsp; <br /> 可以看出Q只要更新过一个表Q?wbr>那么凡是涉及到这个表的查询缓存就失效了,<wbr>因此查询~存的命中率可能会比较低?/font></li> </ul> </ul> <p align="center"><font size="7" face="Calibri">使用二~存的前|条?/font> <br /> </p> <ul> <ul type="DISC"> <li><font size="7" face="Calibri">使用hiberante的应用对数据库具有独占访问权,<wbr>既不能被W三方修Ҏ?因ؓ那样~存不知道你修改了数?<wbr>无法与数据库同步.</font></li> <li><font size="7" face="Calibri">如果自己E序里用了JDBC来更斎ͼ<wbr>不通过hiberante更新,也会出现跟数据库不同步的情况</font></li> </ul> </ul> <img src ="http://www.aygfsteel.com/yuyee/aggbug/336047.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/yuyee/" target="_blank">羊</a> 2010-10-25 00:30 <a href="http://www.aygfsteel.com/yuyee/archive/2010/10/25/336047.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <a href="http://www.aygfsteel.com/" title="狠狠久久亚洲欧美专区_中文字幕亚洲综合久久202_国产精品亚洲第五区在线_日本免费网站视频">狠狠久久亚洲欧美专区_中文字幕亚洲综合久久202_国产精品亚洲第五区在线_日本免费网站视频</a> </div> </footer> վ֩ģ壺 <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">Ͱ</a>| <a href="http://" target="_blank">ɽ</a>| <a href="http://" target="_blank">᯹</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">޻</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">㶫ʡ</a>| <a href="http://" target="_blank">Ž</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">״</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ݸ</a>| <a href="http://" target="_blank">ԫ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ͨ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">̩</a>| <a href="http://" target="_blank">Ͱ</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>