??xml version="1.0" encoding="utf-8" standalone="yes"?>国产精品亚洲一区二区在线观看,亚洲AV永久无码精品一区二区国产 ,亚洲乱码精品久久久久..http://www.tkk7.com/masen/category/22616.htmlzh-cnThu, 26 Mar 2015 17:29:25 GMTThu, 26 Mar 2015 17:29:25 GMT60Spring事务理器的应对 (?http://www.tkk7.com/masen/articles/423831.htmlMasenMasenWed, 25 Mar 2015 10:07:00 GMThttp://www.tkk7.com/masen/articles/423831.htmlhttp://www.tkk7.com/masen/comments/423831.htmlhttp://www.tkk7.com/masen/articles/423831.html#Feedback0http://www.tkk7.com/masen/comments/commentRss/423831.htmlhttp://www.tkk7.com/masen/services/trackbacks/423831.html

Spring事务理器的应对 



   Spring抽象的DAO体系兼容多种数据讉K技术,它们各有特色Q各有千U。像Hibernate是非怼U的ORM实现Ҏ(gu)Q但对底层SQL的控制不太方便;而iBatis则通过模板化技术让你方便地控制SQLQ但没有Hibernate那样高的开发效率;自由度最高的当然是直接用Spring JDBC?jin),但它也是底层的,灉|的代h代码的繁复。很难说哪种数据讉K技术是最优秀的,只有在某U特定的场景下才能给出答案。所以在一个应用中Q往往采用多个数据讉K技术:(x)一般是两种Q一U采用ORM技术框Ӟ而另一U采用偏JDBC的底层技术,两者珠联璧合,形成联合军种Q共同M敌?nbsp;
   但是Q这U联合军U如何应对事务管理的问题呢?我们知道Spring为每U数据访问技术提供了(jin)相应的事务管理器Q难道需要分别ؓ(f)它们配置对应的事务管理器吗?它们到底是如何协作和工作的呢Q这些层ZIL(fng)问题往往压制?jin)开发h员用联合军U的x?nbsp;
   其实Q在q个问题上,我们低估?jin)Spring事务理的能力。如果你采用?jin)一个高端ORM技术(Hibernate、JPA、JDOQ,同时采用一个JDBC技术(Spring JDBC、iBatisQ,׃前者的?x)话QSessionQ是对后者连接(ConnectionQ的装QSpring?#8220;_?#8221;在同一个事务线E让前者的?x)话装后者的q接。所以,我们只要直接采用前者的事务理器就可以?jin)。表10-1l出?jin)؜合数据访问技术框架所对应的事务管理器?nbsp;
?nbsp;   ?/td>混合数据讉K技术框?/td>事务理?/td>
1Hibernate+ Spring JDBC或iBatisorg.springframework.orm.hibernate3.HibernateTransactionManager
2JPA+Spring JDBC或iBatisorg.springframework.orm.jpa.JpaTransactionManager
3JDO+Spring JDBC或iBatisorg.springframework.orm.jdo.JdoTransactionManager


Hibernate+Spring JDBC混合框架的事务管?/span> 


   ׃一般不?x)出现同时用多个ORM框架的情况(如Hibernate+JPAQ,我们不拟Ҏ(gu)命题展开Q只重点研究ORM框架+JDBC框架的情c(din)Hibernate+Spring JDBC可能是被使用得最多的l合Q本节我们通过实例观察事务理的运作情c(din)?nbsp;
Java代码  收藏代码
  1. package com.baobaotao.mixdao;  
  2.   
  3. …  
  4.   
  5. @Service("userService")  
  6. public class UserService extends BaseService {  
  7.     @Autowired  
  8.     private HibernateTemplate hibernateTemplate;  
  9.   
  10.     @Autowired  
  11.     private ScoreService scoreService;  
  12.   
  13.     public void logon(String userName) {  
  14.          
  15.         //①通过Hibernate技术访问数?/span>  
  16.         System.out.println("before updateLastLogonTime()..");  
  17.         updateLastLogonTime(userName);  
  18.         System.out.println("end updateLastLogonTime()..");  
  19.           
  20.         //②通过JDBC技术访问数?/span>  
  21.         System.out.println("before scoreService.addScore()..");  
  22.         scoreService.addScore(userName, 20);  
  23.         System.out.println("end scoreService.addScore()..");  
  24.     }  
  25.       
  26.     public void updateLastLogonTime(String userName) {  
  27.         User user = hibernateTemplate.get(User.class,userName);  
  28.         user.setLastLogonTime(System.currentTimeMillis());  
  29.         hibernateTemplate.update(user);  
  30.   
  31.         //③q句很重要,L(fng)下文的分?/span>  
  32.         hibernateTemplate.flush();  
  33.     }  
  34. }  

  ?#9312;处,使用Hibernate操作数据Q而在②处调用ScoreService#addScore()Q该Ҏ(gu)内部使用Spring JDBC操作数据?nbsp;
  ?#9314;处,我们昑ּ调用?jin)flush()Ҏ(gu)Q将Session中的~存同步到数据库中(即马上向数据库发送一条更新记录的SQL语句Q。之所以要昑ּ执行flush()Ҏ(gu)Q原因是在默认情况下QHibernateҎ(gu)据的更改只是记录在一U缓存中Q要{到事务提交或显式调用flush()Ҏ(gu)时才?x)将一U缓存中的数据同步到数据库中Q而提交事务的操作发生?nbsp;  logon()Ҏ(gu)q回前。如果所有针Ҏ(gu)据库的更Ҏ(gu)作都使用HibernateQ这U数据同步的延迟机制q不?x)生Q何问题。但是,我们在logon()Ҏ(gu)中同旉用了(jin)Hibernate和Spring JDBC混合数据讉K技术,Spring JDBC无法自动感知Hibernate一U缓存,所以如果不?qing)时调用flush()Ҏ(gu)记录数据更改的一U缓存同步到数据库中Q则②处通过Spring JDBCq行数据更改的结果将被Hibernate一U缓存中的更改覆盖掉Q因为Hibernate一U缓存要{到l(f)ogon()Ҏ(gu)q回前才同步到数据库Q?nbsp;
   ScoreService使用Spring JDBC数据讉K技术,其代码如下所C:(x) 
Java代码  收藏代码
  1. package com.baobaotao.mixdao;  
  2.   
  3. import org.springframework.beans.factory.annotation.Autowired;  
  4. import org.springframework.jdbc.core.JdbcTemplate;  
  5. import org.springframework.stereotype.Service;  
  6. import org.apache.commons.dbcp.BasicDataSource;  
  7.   
  8. @Service("scoreService")  
  9. public class ScoreService extends BaseService{  
  10.   
  11.     @Autowired  
  12.     private JdbcTemplate jdbcTemplate;  
  13.   
  14.     public void addScore(String userName, int toAdd) {  
  15.         String sql = "UPDATE t_user u SET u.score = u.score + ? WHERE user_name =?";  
  16.         jdbcTemplate.update(sql, toAdd, userName);  
  17.         BasicDataSource basicDataSource = (BasicDataSource) jdbcTemplate.getDataSource();  
  18.         //①查看此处数据库激zȝq接数量  
  19.         System.out.println("[scoreUserService.addScore]Ȁz连接数量:(x)"  
  20.                          +basicDataSource.getNumActive());  
  21.     }  
  22. }  

   Spring关键的配|文件代码如下所C:(x) 
Xml代码  收藏代码
  1. …  
  2. <!--①使用Hibernate事务理?nbsp;-->  
  3. <bean id="hiberManager"  
  4.       class="org.springframework.orm.hibernate3.HibernateTransactionManager"  
  5.       p:sessionFactory-ref="sessionFactory"/>  
  6.   
  7. <!--②使UserService?qing)ScoreService的公用方法都拥有事务 -->  
  8. <aop:config proxy-target-class="true">  
  9.     <aop:pointcut id="serviceJdbcMethod"  
  10.                   expression="within(com.baobaotao.mixdao.BaseService+)"/>  
  11.     <aop:advisor pointcut-ref="serviceJdbcMethod"  
  12.                  advice-ref="hiberAdvice"/>  
  13. </aop:config>  
  14. <tx:advice id="hiberAdvice" transaction-manager="hiberManager">  
  15.     <tx:attributes>  
  16.         <tx:method name="*"/>  
  17.     </tx:attributes>  
  18. </tx:advice>  
  19.   
  20. /beans>  

启动Spring容器Q执行UserService#logon()Ҏ(gu)Q可以查看到如下的执行日志:(x) 
引用
before userService.logon().. 

①在执行userService.logon()后,Spring开启一个事?/span> 
Creating new transaction with name [com.baobaotao.mixdao.UserService.logon]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT 
opened session at timestamp: 13009379637 
Opened new Session [org.hibernate.impl.SessionImpl@c5f468] for Hibernate transaction 
… 
Exposing Hibernate transaction as JDBC transaction [jdbc:mysql://localhost:3306/sampledb, UserName=root@localhost, MySQL-AB JDBC Driver] 
before userService.updateLastLogonTime().. 

②userService.updateLastLogonTime()执行时自动绑定到①处开启的Session?/span> 
Found thread-bound Session for HibernateTemplate 
loading entity: [com.baobaotao.User#tom] 
about to open PreparedStatement (open PreparedStatements: 0, globally: 0) 
… 
about to close PreparedStatement (open PreparedStatements: 1, globally: 1) 
Not closing pre-bound Hibernate Session after HibernateTemplate 
end updateLastLogonTime().. 

before scoreService.addScore().. 

③scoreService.addScore()执行时绑定到①处开启的Session中,q加入其所对应的事务中 
Found thread-bound Session [org.hibernate.impl.SessionImpl@c5f468] for Hibernate 
transaction 
Participating in existing transaction 
… 
SQL update affected 1 rows 

④此时数据源只打开?jin)一个连?/span> 
[scoreUserService.addScore]Ȁz连接数量:(x)1 
end scoreService.addScore().. 
Initiating transaction commit 

⑤提交Hibernate的事务,它将触发一U缓存到数据库的同步 
Committing Hibernate transaction on Session [org.hibernate.impl.SessionImpl@c5f468] 
commit 
processing flush-time cascades 
dirty checking collections 
Flushed: 0 insertions, 0 updates, 0 deletions to 1 objects 
Flushed: 0 (re)creations, 0 updates, 0 removals to 0 collections 
listing entities: 
com.baobaotao.User{lastLogonTime=1300937963882, score=10, userName=tom, password=123456} 
re-enabling autocommit 

⑥提效Session底层所l定的JDBC Connection所对应的事?/span> 
committed JDBC Connection 
transaction completed on session with on_close connection release mode; be sure to close the session to release JDBC resources! 
Closing Hibernate Session [org.hibernate.impl.SessionImpl@c5f468] after transaction 
Closing Hibernate Session 
releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)] 
transaction completed on session with on_close connection release mode; be sure to close the session to release JDBC resources! 
after userService.logon().. 


   仔细观察q段输出日志Q在①处UserService#logon()开启一个新的事务?#9313;处的UserService# updateLastLogonTime() l定C务上下文的Session中?#9314;处ScoreService#addScore()Ҏ(gu)加入?#9312;处开启的事务上下文中?#9315;处的输出是ScoreService #addScore()Ҏ(gu)内部的输Z息,汇报此时数据源激zȝq接Cؓ(f)1Q这清楚地告诉我们Hibernate和JDBCq两U数据访问技术在同一事务上下文中“q”一个连接。在⑤处,提交Hibernate事务Q接着?#9317;处触发调用底层的Connection提交事务?nbsp;
   从以上的q行l果Q我们可以得?gu)L(fng)l论Q用Hibernate事务理器后Q可以؜合用Hibernate和Spring JDBC数据讉K技术,它们工作于同一事务上下文中。但是用Spring JDBC讉K数据ӞHibernate的一U或二~存得不到同步,此外Q一U缓存gq数据同步机制可能会(x)覆盖Spring JDBC数据更改的结果?nbsp;
   ׃混合数据讉K技术方案存?#8220;事务同步而缓存不同步”的情况,所以最好用Hibernateq行d操作Q而只用Spring JDBCq行L作。如用Spring JDBCq行要列表的查询Q而用HibernateҎ(gu)询出的数据进行维护?nbsp;
   如果实要同时用Hibernate和Spring JDBCd数据Q则必须充分考虑到Hibernate~存机制引发的问题:(x)必须整体分析数据l护逻辑Q根据需要及(qing)时调用Hibernate的flush()Ҏ(gu)Q以免覆盖Spring JDBC的更改,在Spring JDBC更改数据库时Q维护Hibernate的缓存。由于方法调用顺序的不同都可能媄(jing)响数据的同步性,因此很容易发生问题,q会(x)极大提高数据讉KE序的复杂性。所以笔者郑重徏议不要同时用Spring JDBC和HibernateҎ(gu)据进行写操作?nbsp;
   可以以上结论推q到其他混合数据讉K技术的Ҏ(gu)中,如Hibernate+iBatis、JPA+Spring JDBC、JDO+Spring JDBC{?nbsp;


Masen 2015-03-25 18:07 发表评论
]]>
Spring声明式事务管理与配置详解(?http://www.tkk7.com/masen/articles/423824.htmlMasenMasenWed, 25 Mar 2015 07:48:00 GMThttp://www.tkk7.com/masen/articles/423824.htmlhttp://www.tkk7.com/masen/comments/423824.htmlhttp://www.tkk7.com/masen/articles/423824.html#Feedback0http://www.tkk7.com/masen/comments/commentRss/423824.htmlhttp://www.tkk7.com/masen/services/trackbacks/423824.html阅读全文

Masen 2015-03-25 15:48 发表评论
]]>
cron 表达式的格式 (转http://www.tkk7.com/Unmi/archive/2008/02/23/181575.htmlQ作者:(x)隔叶黄莺)http://www.tkk7.com/masen/articles/208816.htmlMasenMasenWed, 18 Jun 2008 03:44:00 GMThttp://www.tkk7.com/masen/articles/208816.htmlhttp://www.tkk7.com/masen/comments/208816.htmlhttp://www.tkk7.com/masen/articles/208816.html#Feedback0http://www.tkk7.com/masen/comments/commentRss/208816.htmlhttp://www.tkk7.com/masen/services/trackbacks/208816.html? cron 表达式的格式

Quartz cron 表达式的格式十分cM?UNIX cron 格式Q但q是有少许明昄区别。区别之一是 Quartz 的格式向下支持到U别的计划Q?UNIX cron 计划仅支持至分钟U。许多我们的触发计划要基于秒U递增?例如Q每45U?Q因此这是一个非常好的差异?br />
?UNIX cron 里,要执行的作业Q或者说命o(h)Q是存放?cron 表达式中的,在第六个域位|上。Quartz ?cron 表达式存放执行计划。引用了(jin) cron 表达式的 CronTrigger 在计划的旉里会(x)?job 兌上?br />
另一个与 UNIX cron 表达式的不同Ҏ(gu)在表辑ּ中支持域的数目。UNIX l出五个?分、时、日、月和周)QQuartz 提供七个域。表 5.1 列出?Quartz cron 表达式支持的七个域?br />
?5.1. Quartz Cron 表达式支持到七个?br />
名称 是否必须 允许?/strong> Ҏ(gu)字符
U?/td> ?/td> 0-59 , - * /
?/td> ?/td> 0-59 , - * /
?/td> ?/td> 0-23 , - * /
?/td> ?/td> 1-31 , - * ? / L W C
?/td> ?/td> 1-12 ?JAN-DEC , - * /
?/td> ?/td> 1-7 ?SUN-SAT , - * ? / L C #
q?/td> ?/td> I??1970-2099 , - * /

月䆾和星期的名称是不区分大小写的?font color="#800080">FRI ?fri 是一L(fng)?br />
域之间有I格分隔Q这?UNIX cron 一栗无可争辩的Q我们能写的最单的表达式看h是q个?jin)?x)

* * * ? * *

q个表达?x)每U钟(每分U的、每时的、每天的)Ȁ发一个部|的 job?br />
·理解Ҏ(gu)字符

?UNIX cron 一PQuartz cron 表达式支持用Ҏ(gu)字符来创建更为复杂的执行计划。然而,Quartz 在特D字W的支持上比标准 UNIX cron 表达式更丰富?jin)?br />
* 星号

使用星号(*) 指示着你想在这个域上包含所有合法的倹{例如,在月份域上用星h味着每个月都?x)触发这?trigger?br />
表达式样例:(x)

0 * 17 * * ?

意义Q每天从下午5点到下午5:59中的每分钟激发一?trigger。它停在下午 5:59 是因为?17 在小时域上,在下?6 Ҏ(gu)Q小时变?18 ?jin),也就不再理?x)q个 triggerQ直C一天的下午5炏V?br />
在你希望 trigger 在该域的所有有效g被激发时使用 * 字符?br />
? 问号

? 号只能用?font color="#800080">?/font>?font color="#800080">周域上,但是不能在这两个域上同时使用。你可以认ؓ(f) ? 字符?"我ƈ不关?j)在该域上是什么倹{? q不同于星号Q星h指示着该域上的每一个倹{? 是说不ؓ(f)该域指定倹{?br />
不能同时q两个域上指定值的理由是难以解释甚x难以理解的。基本上Q假定同时指定值的话,意义׃(x)变得含؜不清?jin)?x)考虑一下,如果一个表辑ּ?font color="#800080">?/font>域上有?1Q同时在?/font>域上指定?WED。那么是?trigger 仅在每个月的11P且正好又是星期三那天被激发?q是在每个星期三?1可Ȁ发呢Q要去除q种不明性的办法是不能同时在这两个域上指定倹{?br />
只要CQ假如你两域的其中一个指定了(jin)|那就必须在另一个字g放一???br />
表达式样例:(x)

0 10,44 14 ? 3 WEB

意义Q在三月中的每个星期三的下午 2:10 ?下午 2:44 被触发?br />
, 逗号

逗号 (,) 是用来在l某个域上指定一个值列表的。例如,使用?0,15,30,45 在秒域上意味着?5U触发一?trigger?br />
表达式样例:(x)

0 0,15,30,45 * * * ?

意义Q每刻钟触发一?trigger?br />
/ 斜杠

斜杠 (/) 是用于时间表的递增的。我们刚刚用?jin)逗号来表C每15分钟的递增Q但是我们也能写成这?0/15?br />
表达式样例:(x)

0/15 0/30 * * * ?

意义Q在整点和半Ҏ(gu)?5U触?trigger?br />
- 中划U?/strong>

中划U?(-) 用于指定一个范围。例如,在小时域上的 3-8 意味着 "3,4,5,6,7 ?8 炏V?  域的g允许回卷Q所以像 50-10 q样的值是不允许的?br />
表达式样例:(x)

0 45 3-8 ? * *

意义Q在上午?点至上午?点的45分时触发 trigger?br />
L 字母

L 说明?jin)某域上允许的最后一个倹{它仅被?/font>?font color="#800080">?/font>域支持。当用在日域上,表示的是?font color="#800080">?/font>域上指定的月份的最后一天。例如,当月域上指定?JAN Ӟ?font color="#800080">?/font>域上?L ?x)?j)?trigger ??1可触发。假?font color="#800080">?/font>域上?SEPQ那?L ?x)预C着??0可发。换句话_(d)是不管指定?jin)哪个月Q都是在相应月䆾的时最后一天触?trigger?br />
表达?0 0 8 L * ? 意义是在每个月最后一天的上午 8:00 触发 trigger。在?/font>域上?* 说明?"每个??br />
?L 字母用于周域上,指示着周的最后一天,是星期?(或者数?)。所以如果你需要在每个月的最后一个星期六下午?11:59 触发 triggerQ你可以用这L(fng)表达?0 59 23 ? * L?br />
当用于?/font>域上Q你可以用一个数字与 L qv来表C月份的最后一个星?X。例如,表达?0 0 12 ? * 2L 说的是在每个月的最后一个星期一触发 trigger?br />
不要让范围和列表g L q用

虽然你能用星期数(1-7)?L q用Q但是不允许你用一个范围值和列表g L q用。这?x)生不可预知的l果?/td>

W 字母

W 字符代表着qx (Mon-Fri)Qƈ且仅能用于日域中。它用来指定L定日的最q的一个^日。大部分的商业处理都是基于工作周的,所?W 字符可能是非帔R要的。例如,日域中的 15W 意味着 "该?5L(fng)最q一个^日? 假如15h星期六,那么 trigger ?x)?4?星期?触发Q因15hq的是星期一Q这个例子中也会(x)?7?font color="#0000ff">Q译者Unmi注:(x)不会(x)?7可发的Q如果是15WQ可能会(x)是在14?15h星期?或?5?15h星期?触发Q也是只能出现在邻q的一天,如果15号当天ؓ(f)qx直接׃(x)当日执行Q?/font>?font color="#800080">W
只能用在指定?font color="#800080">?/font>域ؓ(f)单天Q不能是范围或列表倹{?br />
# 井号

# 字符仅能用于?/font>域中。它用于指定月䆾中的W几周的哪一天。例如,如果你指定周域的gؓ(f) 6#3Q它意思是某月的第三个周五 (6=星期五,#3意味着月䆾中的W三?。另一个例?2#1 意思是某月的第一个星期一 (2=星期一Q?font color="#800080">#1意味着月䆾中的W一?。注意,假如你指?#5Q然而月份中没有W?5 周,那么该月不会(x)触发?br />


[版权声明]
本站内文章,如未标注 [转蝲]Q均pd创或译之作Q本?Unmi 保留一切权利。本站原创及(qing)译作未经本h许可Q不得用于商业用途及(qing)传统媒体。网l媒体可随意转蝲Q或以此为基q行演译Q但务必以链接Ş式注明原始出处和作者信息,否则属于侉|行ؓ(f)。另Ҏ(gu)站{载他处文章,俱有说明Q如有R权请联系本hQ本人将?x)在W一旉删除侉|文章。及(qing)此说明,重之之重?/font>

Masen 2008-06-18 11:44 发表评论
]]>
详解spring事务属??http://www.tkk7.com/masen/articles/208548.htmlMasenMasenTue, 17 Jun 2008 03:02:00 GMThttp://www.tkk7.com/masen/articles/208548.htmlhttp://www.tkk7.com/masen/comments/208548.htmlhttp://www.tkk7.com/masen/articles/208548.html#Feedback0http://www.tkk7.com/masen/comments/commentRss/208548.htmlhttp://www.tkk7.com/masen/services/trackbacks/208548.htmlSpring声明式事务让我们从复杂的事务处理中得到解脱。得我们再也无需要去处理获得q接、关闭连接、事务提交和回滚{这些操作。再也无需要我们在与事务相关的Ҏ(gu)中处理大量的try…catch…finally代码?
我们在用Spring声明式事务时Q有一个非帔R要的概念是事务属性。事务属性通常׃务的传播行ؓ(f)Q事务的隔离U别Q事务的时值和事务只读标志l成。我们在q行事务划分Ӟ需要进行事务定义,也就是配|事务的属性?
Spring?strong>TransactionDefinition
接口中定义这些属?以供PlatfromTransactionManager使用, PlatfromTransactionManager是spring事务理的核?j)接口?

代码
  1. TransactionDefinition   
  2. public interface TransactionDefinition {   
  3.     int getPropagationBehavior();   
  4.     int getIsolationLevel();   
  5.     int getTimeout();   
  6.     boolean isReadOnly();   
  7. }  

 

getTimeout()Ҏ(gu)Q它q回事务必须在多秒内完成?
isReadOnly(),事务是否只读Q事务管理器能够Ҏ(gu)q个q回D行优化,保事务是只ȝ?
getIsolationLevel()Ҏ(gu)q回事务的隔ȝ别,事务理器根据它来控制另外一个事务可以看到本事务内的哪些数据?/p>

在TransactionDefinition接口中定义了(jin)五个不同的事务隔ȝ?
ISOLATION_DEFAULT q是一个PlatfromTransactionManager默认的隔ȝ别,使用数据库默认的事务隔离U别.另外四个与JDBC的隔ȝ别相对应
ISOLATION_READ_UNCOMMITTED q是事务最低的隔离U别Q它充许别外一个事务可以看到这个事务未提交的数据。这U隔ȝ别会(x)产生脏读Q不可重复读和像读?
例如:
Mary的原工资?000,财务人员Mary的工资改Z(jin)8000Q但未提交事?

代码
  1. Connection con1 = getConnection();   
  2. con.setAutoCommit(false);   
  3. update employee set salary = 8000 where empId ="Mary";  

与此同时QMary正在d自己的工?
代码
  1. Connection con2 = getConnection();   
  2. select   salary from employee where empId ="Mary";   
  3. con2.commit();  

 

Mary发现自己的工资变Z(jin)8000Q欢天喜圎ͼ
而胦(ch)务发现操作有误,而回滚了(jin)事务,Mary的工资又变ؓ(f)?000

代码
  1. //con1   
  2.    con1.rollback();  

像这?Mary记取的工资数8000是一个脏数据?

 

ISOLATION_READ_COMMITTED 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。这U事务隔ȝ别可以避免脏d玎ͼ但是可能?x)出C可重复读和像读?/p>

ISOLATION_REPEATABLE_READ q种事务隔离U别可以防止脏读Q不可重复读。但是可能出现像读。它除了(jin)保证一个事务不能读取另一个事务未提交的数据外Q还保证?jin)避免下面的情况产?不可重复??/p>

在事?中,Mary d?jin)自q工资?000,操作q没有完?

代码
  1. con1 = getConnection();   
  2. select salary from employee empId ="Mary";  

 

在事?中,q时财务人员修改?jin)Mary的工资ؓ(f)2000,q提交了(jin)事务.

代码
  1. con2 = getConnection();   
  2. update employee set salary = 2000;   
  3. con2.commit();  

 

在事?中,Mary 再次d自己的工资时Q工资变Z(jin)2000

代码
  1. //con1   
  2. select salary from employee empId ="Mary";  

 

在一个事务中前后两次d的结果ƈ不致Q导致了(jin)不可重复诅R?
使用ISOLATION_REPEATABLE_READ可以避免q种情况发生?/p>

ISOLATION_SERIALIZABLE q是p最高代价但是最可靠的事务隔ȝ别。事务被处理为顺序执行。除?jin)防止脏读,不可重复dQ还避免?jin)像读?/p>

目前工资?000的员工有10人?
事务1,d所有工资ؓ(f)1000的员工?

代码
  1. con1 = getConnection();   
  2. Select * from employee where salary =1000;  
p?0条记?

 

q时另一个事务向employee表插入了(jin)一条员工记录,工资也ؓ(f)1000

代码
  1. con2 = getConnection();   
  2. Insert into employee(empId,salary) values("Lili",1000);   
  3. con2.commit();  

 

事务1再次d所有工资ؓ(f)1000的员?

代码
  1. //con1   
  2. select * from employee where salary =1000;  

 

p取到?1条记录,q就产生?jin)像读?
ISOLATION_SERIALIZABLE能避免这L(fng)情况发生。但是这样也耗费?jin)最大的资源?/p>

getPropagationBehavior()q回事务的传播行为,由是否有一个活动的事务来决定一个事务调用?/p>

在TransactionDefinition接口中定义了(jin)七个事务传播行ؓ(f)?/p>

PROPAGATION_REQUIRED 如果存在一个事务,则支持当前事务。如果没有事务则开启一个新的事务?/p>

 

代码
  1. //事务属?PROPAGATION_REQUIRED   
  2. methodA{   
  3. ……   
  4. methodB();   
  5. ……   
  6. }   
  7.   
  8. //事务属?PROPAGATION_REQUIRED   
  9. methodB{   
  10.     ……   
  11. }  

使用spring声明式事务,spring使用AOP来支持声明式事务Q会(x)Ҏ(gu)事务属性,自动在方法调用之前决定是否开启一个事务,q在Ҏ(gu)执行之后军_事务提交或回滚事务?

 

单独调用methodBҎ(gu)

代码
  1. main{   
  2.    metodB();   
  3. }  

相当?
代码
  1. Main{   
  2. Connection con=null;   
  3.   
  4.     rry{   
  5.        con = getConnection();   
  6.        con.setAutoCommit(false);   
  7. //Ҏ(gu)调用   
  8. methodB();   
  9. //提交事务   
  10. con.commit();   
  11. }   
  12. Catch(RuntimeException ex){   
  13.   //回滚事务   
  14.    con.rollback();     
  15. }   
  16. finally{   
  17.   //释放资源   
  18.    closeCon();   
  19. }   
  20. }  

Spring保证在methodBҎ(gu)中所有的调用都获得到一个相同的q接。在调用methodBӞ没有一个存在的事务Q所以获得一个新的连接,开启了(jin)一个新的事务?

 

单独调用MethodAӞ在MethodA内又?x)调用MethodB.

执行效果相当?

代码
  1. main{   
  2.     Connection con = null;   
  3.    try{   
  4.        con = getConnection();   
  5.        methodA();   
  6.        con.commit();   
  7. }   
  8. cathc(RuntimeException ex){   
  9. con.rollback();   
  10. }   
  11. finally{   
  12.    closeCon();   
  13. }    
  14. }  

调用MethodAӞ环境中没有事务,所以开启一个新的事?
当在MethodA中调用MethodBӞ环境中已l有?jin)一个事务,所以methodB加入当前事务?

 

PROPAGATION_SUPPORTS 如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行。但是对于事务同步的事务理器,PROPAGATION_SUPPORTS与不使用事务有少怸同?/p>

 

代码
  1. //事务属?PROPAGATION_REQUIRED    
  2. methodA(){   
  3.    methodB();   
  4. }   
  5.   
  6. //事务属?PROPAGATION_SUPPORTS    
  7. methodB(){   
  8.    ……   
  9. }  

单纯的调用methodBӞmethodBҎ(gu)是非事务的执行的?
当调用methdA?methodB则加入了(jin)methodA的事务中,事务地执行?

 

PROPAGATION_MANDATORY 如果已经存在一个事务,支持当前事务。如果没有一个活动的事务Q则抛出异常?/p>

 

代码
  1. //事务属?PROPAGATION_REQUIRED    
  2. methodA(){   
  3.    methodB();   
  4. }   
  5.   
  6. //事务属?PROPAGATION_MANDATORY    
  7. methodB(){   
  8.    ……   
  9. }  

当单独调用methodBӞ因ؓ(f)当前没有一个活动的事务Q则?x)抛出异?
throw new IllegalTransactionStateException("Transaction propagation 'mandatory' but no existing transaction found");

 

当调用methodAӞmethodB则加入到methodA的事务中Q事务地执行?/p>

PROPAGATION_REQUIRES_NEW L开启一个新的事务。如果一个事务已l存在,则将q个存在的事务挂赗?/p>

 

代码
  1. //事务属?PROPAGATION_REQUIRED    
  2. methodA(){   
  3.    doSomeThingA();   
  4. methodB();   
  5. doSomeThingB();   
  6. }   
  7.   
  8. //事务属?PROPAGATION_REQUIRES_NEW    
  9. methodB(){   
  10.    ……   
  11. }  

当单独调用methodBӞ相当于把methodb声明为REQUIRED。开启一个新的事务,事务地执行?

 

当调用methodA?

代码
  1. main(){   
  2.    methodA();   
  3. }  
情况有些大不一?相当于下面的效果?
代码
  1. main(){   
  2. TransactionManager tm = null;   
  3. try{   
  4.   //获得一个JTA事务理?  
  5.     tm = getTransactionManager();   
  6.     tm.begin();//开启一个新的事?  
  7.     Transaction ts1 = tm.getTransaction();   
  8.     doSomeThing();   
  9.     tm.suspend();//挂v当前事务   
  10.    try{   
  11.       tm.begin();//重新开启第二个事务   
  12.       Transaction ts2 = tm.getTransaction();   
  13.       methodB();   
  14.       ts2.commit();//提交W二个事?  
  15.         
  16.     }   
  17.    Catch(RunTimeException ex){   
  18.       ts2.rollback();//回滚W二个事?  
  19.    }   
  20.   finally{   
  21.     //释放资源   
  22.    }   
  23.    //methodB执行完后Q复恢第一个事?  
  24.     tm.resume(ts1);   
  25. doSomeThingB();   
  26.     ts1.commit();//提交W一个事?  
  27. }   
  28. catch(RunTimeException ex){   
  29.    ts1.rollback();//回滚W一个事?  
  30. }   
  31. finally{   
  32.   //释放资源   
  33. }   
  34. }  

在这里,我把ts1UCؓ(f)外层事务Qts2UCؓ(f)内层事务。从上面的代码可以看出,ts2与ts1是两个独立的事务Q互不相qӀTs2是否成功q不依赖于ts1。如果methodAҎ(gu)在调用methodBҎ(gu)后的doSomeThingBҎ(gu)p|?jin),而methodBҎ(gu)所做的l果依然被提交。而除?jin)methodB之外的其它代码导致的l果却被回滚?jin)?
使用PROPAGATION_REQUIRES_NEW,需要用JtaTransactionManager作ؓ(f)事务理器?

 

PROPAGATION_NOT_SUPPORTED L非事务地执行Qƈ挂vM存在的事务?/p>

 

代码
  1. //事务属?PROPAGATION_REQUIRED    
  2. methodA(){   
  3.    doSomeThingA();   
  4. methodB();   
  5. doSomeThingB();   
  6. }   
  7.   
  8. //事务属?PROPAGATION_NOT_SUPPORTED    
  9. methodB(){   
  10.    ……   
  11. }  

当单独调用methodBӞ不启用Q何事务机Ӟ非事务地执行?
当调用methodAӞ相当于下面的效果

 

 

代码
  1. main(){   
  2. TransactionManager tm = null;   
  3. try{   
  4.   //获得一个JTA事务理?  
  5.     tm = getTransactionManager();   
  6.     tm.begin();//开启一个新的事?  
  7.     Transaction ts1 = tm.getTransaction();   
  8.     doSomeThing();   
  9.     tm.suspend();//挂v当前事务   
  10.       methodB();   
  11.    //methodB执行完后Q复恢第一个事?  
  12.     tm.resume(ts1);   
  13. doSomeThingB();   
  14.     ts1.commit();//提交W一个事?  
  15. }   
  16. catch(RunTimeException ex){   
  17.    ts1.rollback();//回滚W一个事?  
  18. }   
  19. finally{   
  20.   //释放资源   
  21. }   
  22. }  
使用PROPAGATION_NOT_SUPPORTED,也需要用JtaTransactionManager作ؓ(f)事务理器?

 

PROPAGATION_NEVER L非事务地执行Q如果存在一个活动事务,则抛出异?/p>

 

代码
  1. //事务属?PROPAGATION_REQUIRED    
  2. methodA(){   
  3.    doSomeThingA();   
  4. methodB();   
  5. doSomeThingB();   
  6. }   
  7.   
  8. //事务属?PROPAGATION_NEVER    
  9. methodB(){   
  10.    ……   
  11. }  
单独调用methodBQ则非事务的执行?
调用methodA则会(x)抛出异常
throw new IllegalTransactionStateException(
"Transaction propagation 'never' but existing transaction found");

 

PROPAGATION_NESTED如果一个活动的事务存在Q则q行在一个嵌套的事务? 如果没有zd事务, 则按TransactionDefinition.PROPAGATION_REQUIRED 属性执?/p>

q是一个嵌套事?使用JDBC 3.0驱动?仅仅支持DataSourceTransactionManager作ؓ(f)事务理器。需要JDBC 驱动的java.sql.SavepointcR有一些JTA的事务管理器实现可能也提供了(jin)同样的功能?/p>

使用PROPAGATION_NESTEDQ还需要把PlatformTransactionManager的nestedTransactionAllowed属性设为true;
而nestedTransactionAllowed属性值默认ؓ(f)false;

代码
  1. //事务属?PROPAGATION_REQUIRED    
  2. methodA(){   
  3.    doSomeThingA();   
  4. methodB();   
  5. doSomeThingB();   
  6. }   
  7.   
  8. //事务属?PROPAGATION_NESTED   
  9. methodB(){   
  10.    ……   
  11. }  

如果单独调用methodBҎ(gu)Q则按REQUIRED属性执行?

 

如果调用methodAҎ(gu)Q相当于下面的效?

代码
  1. main(){   
  2. Connection con = null;   
  3. Savepoint savepoint = null;   
  4. try{   
  5.    con = getConnection();   
  6.    con.setAutoCommit(false);   
  7.    doSomeThingA();   
  8.    savepoint = con2.setSavepoint();   
  9.   try  
  10.        methodB();   
  11.    }catch(RuntimeException ex){   
  12.       con.rollback(savepoint);   
  13.    }   
  14.   finally{   
  15.     //释放资源   
  16.    }   
  17.   
  18.    doSomeThingB();   
  19.    con.commit();   
  20. }   
  21. catch(RuntimeException ex){   
  22.    con.rollback();   
  23. }   
  24. finally{   
  25.   //释放资源   
  26. }   
  27. }  
当methodBҎ(gu)调用之前Q调用setSavepointҎ(gu)Q保存当前的状态到savepoint。如果methodBҎ(gu)调用p|Q则恢复C前保存的状态。但是需要注意的是,q时的事务ƈ没有q行提交Q如果后l的代码(doSomeThingB()Ҏ(gu))调用p|Q则回滚包括methodBҎ(gu)的所有操作?

 

嵌套事务一个非帔R要的概念是内层事务依赖于外层事务。外层事务失败时Q会(x)回滚内层事务所做的动作。而内层事务操作失败ƈ不会(x)引v外层事务的回?/strong>?/p>

PROPAGATION_NESTED 与PROPAGATION_REQUIRES_NEW的区?/strong>:它们非常cM,都像一个嵌套事务,如果不存在一个活动的事务Q都?x)开启一个新的事务。用PROPAGATION_REQUIRES_NEWӞ内层事务与外层事务就像两个独立的事务一P一旦内层事务进行了(jin)提交后,外层事务不能对其q行回滚。两个事务互不媄(jing)响。两个事务不是一个真正的嵌套事务。同时它需要JTA事务理器的支持?
使用PROPAGATION_NESTEDӞ外层事务的回滚可以引起内层事务的回滚。而内层事务的异常q不?x)导致外层事务的回滚Q它是一个真正的嵌套事务。DataSourceTransactionManager使用savepoint支持PROPAGATION_NESTEDӞ需要JDBC 3.0以上驱动?.4以上的JDK版本支持。其它的JTA TrasactionManager实现可能有不同的支持方式?/p>

PROPAGATION_REQUIRED应该是我们首先的事务传播行ؓ(f)。它能够满我们大多数的事务需求?/p>

Masen 2008-06-17 11:02 发表评论
]]>
spring事务相关Q{Q?/title><link>http://www.tkk7.com/masen/articles/206269.html</link><dc:creator>Masen</dc:creator><author>Masen</author><pubDate>Fri, 06 Jun 2008 03:12:00 GMT</pubDate><guid>http://www.tkk7.com/masen/articles/206269.html</guid><wfw:comment>http://www.tkk7.com/masen/comments/206269.html</wfw:comment><comments>http://www.tkk7.com/masen/articles/206269.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/masen/comments/commentRss/206269.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/masen/services/trackbacks/206269.html</trackback:ping><description><![CDATA[<h1 class="block_title"><a id="viewpost1_TitleUrl" href="http://www.tkk7.com/baoyaer/articles/93060.html">spring事务理</a></h1> <div id="tdqhnto" class="post"> <div id="mlyoxhr" class="postcontent">通常通过TransactionProxyFactoryBean讄Spring事务代理。我们需要一个目标对象包装在事务代理中。这个目标对象一般是一个普通Java对象的bean。当我们定义TransactionProxyFactoryBeanӞ必须提供一个相关的 PlatformTransactionManager的引用和<strong>事务属?/strong>?<strong>事务属?/strong>含有上面描述的事务定义? <pre><bean id="petStore" <br />     class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"><br />     <property name="transactionManager"><ref bean="transactionManager"/></property><br />     <property name="target"><ref bean="petStoreTarget"/></property><br />     <property name="transactionAttributes"><br />         <props><br />             <prop key="insert*">PROPAGATION_REQUIRED,-MyCheckedException</prop><br />             <prop key="update*">PROPAGATION_REQUIRED</prop><br />             <prop key="*">PROPAGATION_REQUIRED,readOnly</prop><br />         </props><br />     </property><br /> </bean></pre> <p>事务代理?x)实现目标对象的接口Q这里是id为petStoreTarget的bean。(使用 CGLIB也可以实现具体类的代理。只要设|proxyTargetClass属性ؓ(f)true可以。如果目标对象没有实CQ何接口,q将自动讄该属性ؓ(f)true。通常Q我们希望面向接口而不是类~程。)(j)使用proxyInterfaces属性来限定事务代理来代 理指定接口也是可以的<img alt="" src="http://blog.csdn.net/fckeditor/editor/images/smiley/msn/angry_smile.gif" />Q一般来说是个好xQ。也可以通过?<tt><font face="新宋?>org.springframework.aop.framework.ProxyConfig</font></tt>l承或所有AOP代理工厂׃n 的属性来定制TransactionProxyFactoryBean的行为?</p> <p>q里的transactionAttributes属性定义在 <tt><font face="新宋?>org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource</font></tt> 中的属性格式来讄。这个包括通配W的Ҏ(gu)名称映射是很直观的。注?insert*的映的值包括回滚规则。添加的<tt><font face="新宋?>-MyCheckedException</font></tt> 指定如果Ҏ(gu)抛出<tt><font face="新宋?>MyCheckedException</font></tt>或它的子c,事务??x)自动回滚。可以用逗号分隔定义多个回滚规则?font color="#ff0000"><strong>-前缀强制回滚Q?前缀指定提交</strong></font>Q这允许即抛出unchecked异常时也可以提交事务Q当然你自己要明白自?在做什么)(j)?/p> <p><tt><font face="新宋?>TransactionProxyFactoryBean</font></tt>允许你通过 “preInterceptors”?#8220;postInterceptors”属性设|?#8220;?#8221;?#8220;?#8221;通知来提供额外的 拦截行ؓ(f)。可以设|Q意数量的“?#8221;?#8220;?#8221;通知Q它们的cd可以?<tt><font face="新宋?>Advisor</font></tt>Q可以包含一个切入点Q, <tt><font face="新宋?>MethodInterceptor</font></tt>或被当前Spring配置支持的通知cd Q例?tt><font face="新宋?>ThrowAdvice</font></tt>Q?<tt><font face="新宋?>AfterReturningtAdvice</font></tt>?tt><font face="新宋?>BeforeAdvice</font></tt>Q?q些都是默认支持的)(j)。这些通知必须支持实例׃n模式。如果你需要高UAOP?性来使用事务Q如有状态的maxinQ那最好用通用?<tt><font face="新宋?>org.springframework.aop.framework.ProxyFactoryBean</font></tt>Q?而不?tt><font face="新宋?>TransactionProxyFactoryBean</font></tt>实用代理创徏者?/p> <p>也可以设|自动代理:(x)配置AOP框架Q不需要单独的代理定义cd可以生成cȝ 代理?/p> <p>附两个spring的事务配|例子:(x)<br /> <prop key="add"><br />      PROPAGATION_REQUIRES_NEW, -MyException <br /> </prop><br /> 注:(x)上面的意思是addҎ(gu)独占一个事务,当事务处理过E中产生MyException异常或者该异常的子cd回滚该事务?br /> <br /> <prop key="loadAll"><br />     PROPAGATION_SUPPORTS, ISOLATION_READ_COMMITED, Readonly<br /> </prop><br /> 注:(x)表示loadAllҎ(gu)支持事务Q而且不会(x)d没有提交事务的数据。它的数据ؓ(f)只读Q这h助于提高d的性能Q?br /> <br /> 附A Spring中的所有事务策?br /> <br /> PROPAGATION_MANDATORY<br /> PROPAGATION_NESTED <br /> PROPAGATION_NEVER <br /> PROPAGATION_NOT_SUPPORTED<br /> PROPAGATION_REQUIRED<br /> PROPAGATION_REQUIRED_NEW<br /> PROPAGATION_SUPPORTS<br /> <br /> 附B Spring中所有的隔离{略Q?br /> <br /> ISOLATION_DEFAULT<br /> ISOLATION_READ_UNCOMMITED<br /> ISOLATION_COMMITED<br /> ISOLATION_REPEATABLE_READ<br /> ISOLATION_SERIALIZABLE </p> <p><a href="http://www.tkk7.com/DenisLing/archive/2005/12/18/spring.html" target="_blank"><font color="#000000" size="6"><strong>Spring事务cd解</strong></font></a><font size="6"><strong></strong></font></p> <p>大家可能在spring中经常看到这L(fng)定义Q?/p> <p> </p> <p><prop key="load*">PROPAGATION_REQUIRED,readOnly</prop><prop key="store*">PROPAGATION_REQUIRED</prop></p> <p>估计有好多朋友还没有弄清楚里面的值的意思,仔细看完下面应该知道自己什么情况下面应该用什么样的声明。^_^<br /> </p> <p> </p> <p>Spring中常用事务类型:(x)<br /> </p> <ul> <li>PROPAGATION_REQUIRED--支持当前事务Q如果当前没有事务,新Z个事务。这是最常见的选择?<br /> <li>PROPAGATION_SUPPORTS--支持当前事务Q如果当前没有事务,׃非事务方式执行?<br /> <li>PROPAGATION_MANDATORY--支持当前事务Q如果当前没有事务,抛出异常?<br /> <li>PROPAGATION_REQUIRES_NEW--新徏事务Q如果当前存在事务,把当前事务挂赗?<br /> <li>PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作Q如果当前存在事务,把当前事务挂v?<br /> <li>PROPAGATION_NEVER--以非事务方式执行Q如果当前存在事务,则抛出异常?<br /> <li>PROPAGATION_NESTED--如果当前存在事务Q则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIREDcM的操作?br /> </li> </ul> <div class="ojluakb" id="articleview_summary">摘要Q?br /> Spring和EJB一P提供?jin)两U事务管理方式:(x)~程式和声明式。在考试pȝ中我们将使用声明式的事务理Q这是spring推荐的做法。用这U方式可以体验到spring的强大便P而且我们无须在DaocM~写MҎ(gu)的代码,只需要通过配置文g可以让普通的javacd载到事务理中,q个意义是很重大的?<br /> <br /> <br /> 本文Matrix怹镜像Q?a >http://www.matrix.org.cn/resource/article/1/1339.html</a><br /> 说明Q本文可能由Matrix原创Q也可能由Matrix的会(x)员整理,或者由<br /> Matrix的Crawler在全球知名Java或者其他技术相关站Ҏ(gu)取ƈ怹<br /> 保留镜像QMatrix?x)保留所有原来的出处URLQƈ在显著地方作?gu)明?br /> 如果你发觉出处URL有误Q请联系MatrixҎ(gu).<br /> </div> <div class="dyljllv" id="divarticlecontent">四、Spring中的事务控制<br /> <br /> Spring和EJB一P提供?jin)两U事务管理方式:(x)~程式和声明式。在考试pȝ中我们将使用声明式的事务理Q这是spring推荐的做法。用这U方式可以体验到spring的强大便P而且我们无须在DaocM~写MҎ(gu)的代码,只需要通过配置文g可以让普通的javacd载到事务理中,q个意义是很重大的?br /> <br /> Spring中进行事务管理的通常方式是利用AOPQ面向切片编E)(j)的方式,为普通javacd装事务控Ӟ它是通过动态代理实现的Q由于接口是延迟实例化的Qspring在这D|间内通过拦截器,加蝲事务切片。原理就是这P具体l节请参考jdk中有兛_态代理的文档。本文主要讲解如何在spring中进行事务控制?br /> <br /> 动态代理的一个重要特征是Q它是针Ҏ(gu)口的Q所以我们的dao要通过动态代理来让spring接管事务Q就必须在dao前面抽象Z个接口,当然如果没有q样的接口,那么spring?x)用CGLIB来解决问题,但这不是spring推荐的方式,我们也不做讨论?br /> <br /> 参照前面的例子,我们为StudentManager.java定义一个接口,它的内容如下Q?br /> <br /> <pre class="overflow" title="pre code">/*<br /> * 创徏日期 2005-3-25<br /> */<br /> package org.bromon.spring.examer.student;<br /> <br /> import java.util.List;<br /> <br /> import org.bromon.spring.examer.pojo.Student;<br /> <br /> /**<br /> * @author Bromon<br /> */<br /> public interface StudentManagerInterface<br /> {<br />     public void add(Student s);<br />     public void del(Student s);<br />     public void update(Student s);<br />     <br />     public List loadAll();<br />     public Student loadById(int id);<br /> }</pre> <br /> StudentManager也应该做Z改,实现该接口:(x)<br /> <br /> <pre class="overflow" title="pre code">public class StudentManager extends HibernateDaoSupport implements StudentManagerInterface</pre> <br /> 现在需要修攚w|文Ӟ用于定义Hibrenate适用的事务管理器Qƈ且把sessionFactory注入q去Q同时还需要通过注册一个DefaultTransactionAttribute对象Q来指出事务{略。其中sessionFactory的定义已l在本文的第三章中说明?br /> <br /> 首先定义一个Hibernate的事务管理器Q让它来理sessionFactoryQ?br /> <pre class="overflow" title="pre code"><bean id="transactionManager" class="org.springframework.orm.hibernate.HibernateTransactionManager"><br />       <property name="sessionFactory"><br />          <ref bean="sessionFactory"/><br />       </property><br /> </bean></pre> <br /> 下面定义事务理{略Q我们希望把{略定义在方法这个别上Q提供最大的灉|性,本例中将addҎ(gu)定义为:(x)PROPAGATION_REQUIRES_NEWQ这可以保证它将始终q行在一个事务中?br /> <br /> <pre class="overflow" title="pre code"><bean id="transactionAttributeSource" class="org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource"><br />       <property name="properties"><br />          <props><br />             <prop key="add"><br />                PROPAGATION_REQUIRES_NEW<br />             </prop><br />          </props><br />       </property><br />    </bean></pre> <br /> 我们不仅可以为addҎ(gu)定义事务{略,q可以定义事务隔ȝ度和回滚{略,他们以逗号隔开,比如我们的add事务可以定义?<br /> <br /> <pre class="overflow" title="pre code"><prop key="add"><br />    PROPAGATION_REQUIRES_NEW,-ExamerException<br /> </prop</pre> ><br /> <br /> q个事务{略表示addҎ(gu)会(x)独占一个事务,当事务过E中产生ExamerException异常Q事务会(x)回滚?br /> <br /> Add/update/del都是写入Ҏ(gu)Q对于selectQ读取)(j)Ҏ(gu)Q我们可以指定较为复杂的事务{略Q比如对于loadAll()Ҏ(gu)Q?br /> <br /> <pre class="overflow" title="pre code"><prop key=”loadAll”><br />       PROPAGATION_SUPPORTS,ISOLATION_READ_COMMITED,readOnly<br />    </prop></pre> <br /> <br /> 该事务的含义为,loadAllҎ(gu)支持事务Q不?x)读M提交的数据,它的数据为只读(可提高执行速度Q?br /> <br /> 如你所见,我们的StudentManagerInterface接口中还有一个loadById(int id)Ҏ(gu)Q也许我们将来还?x)有很多的loadByXXXX的方法,N要意义ؓ(f)他们指定事务{略Q太?ch)h?jin),他们应该和loadAll()一P所以我们可以用通配W,定义所有的loadXXXXҎ(gu)Q?br /> <br /> <pre class="overflow" title="pre code"><prop key=”load*”><br />       PROPAGATION_SUPPORTS,ISOLATION_READ_COMMITED,readOnly<br />    </prop></pre> <br /> <br /> 现在可以定义事务理器:(x)<br /> <pre class="overflow" title="pre code"><bean id="studentManager" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"><br />       <property name="target"><br />          <ref bean="studentManager"/><br />       </property><br />       <property name="transactionManager"><br />          <ref bean="transactionManager"/><br />       </property><br />       <property name="transactionAttributeSource"><br />          <ref bean="transactionAttributeSource"/><br />       </property><br /> </bean></pre> <br /> <br /> q个bean的外观是一个接?StudentManagerInterface)Q我们指Z(jin)它的具体实现(studentManager)Q而且为它l定?jin)事务策略。在客户端用的时候,获得对象是StudentManagerInterfaceQ所有的操作都是针对q个接口的。测试代码ƈ没有改变Q我们虽然修改了(jin)很多地方Q加入了(jin)事务控制Q但是客L(fng)q没有受到媄(jing)响,q也体现?jin)spring的一些优ѝ测试代码如下:(x)<br /> <br /> <pre class="overflow" title="pre code">public void testAdd() <br />     {<br />         ApplicationContext ctx=new ClassPathXmlApplicationContext("springConfig.xml");<br />         StudentManager sm=(StudentManager)ctx.getBean("studentManager");<br />         <br />         Student s=new Student();<br />         s.setId(1);<br />         s.setName("bromon");<br />         s.setPassword("123");<br />         s.setGrade(1);<br />         s.setSex(0);<br />         <br />         sm.add(s);<br /> }</pre> <br /> <br /> 通过以上的代码可以看出,spring可以单的把普通的java classU_事务理Q声明性的事务操作h也很Ҏ(gu)。有?jin)spring之后Q声明性事务不再是EJB独有Q我们不必ؓ(f)?jin)获得声明性事务的功能而去忍受EJB带来的种U不ѝ?br /> <br /> 我所使用的mysql是不支持事务的,你可以更换用PostgreSQLQ有?jin)spring+hibernateQ更换dbq不像以前那h怖了(jin)Q步骤很单:(x)<br /> <br /> 1?dPostgreSQL的jdbc驱动<br /> 2?修改dataSource配置Q包括驱动名U、url、帐受密?br /> 3?修改sessionFactory的数据库dailet为net.sf.hibernate.dialect.PostgreSQLDialect<br /> 4?修改hbm.xml中的主键生成{略为increment<br /> <br /> 所有的修改都在配置文g中完成,业务代码不需要Q何修改,我很满意QHow about u?<br /> </div> <p> </p> <p> </p> <h2><a id="viewpost1_TitleUrl" href="http://www.tkk7.com/kaktos/archive/2006/03/08/34301.html">spring声明式事务管理的两种方式</a></h2> <div id="toboqsv" class="postText">传统的:(x)<br /> <div style="border-right: rgb(204,204,204) 1px solid; padding-right: 5px; border-top: rgb(204,204,204) 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: rgb(204,204,204) 1px solid; width: 98%; padding-top: 4px; border-bottom: rgb(204,204,204) 1px solid; background-color: rgb(238,238,238)"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: rgb(0,128,128)"> <font size="1">1</font></span><font size="1"> <span style="color: rgb(0,0,255)"><</span><span style="color: rgb(128,0,0)">bean </span><span style="color: rgb(255,0,0)">id</span><span style="color: rgb(0,0,255)">="dataSource"</span><span style="color: rgb(255,0,0)"> class</span><span style="color: rgb(0,0,255)">="org.apache.commons.dbcp.BasicDataSource"</span><span style="color: rgb(255,0,0)"> destroy-method</span><span style="color: rgb(0,0,255)">="close"</span><span style="color: rgb(0,0,255)">></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)"> 2</span> <span style="color: rgb(0,0,0)">        </span><span style="color: rgb(0,0,255)"><</span><span style="color: rgb(128,0,0)">property </span><span style="color: rgb(255,0,0)">name</span><span style="color: rgb(0,0,255)">="driverClassName"</span><span style="color: rgb(255,0,0)"> value</span><span style="color: rgb(0,0,255)">="oracle.jdbc.driver.OracleDriver"</span><span style="color: rgb(255,0,0)"> </span><span style="color: rgb(0,0,255)">/></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)"> 3</span> <span style="color: rgb(0,0,0)">        </span><span style="color: rgb(0,0,255)"><</span><span style="color: rgb(128,0,0)">property </span><span style="color: rgb(255,0,0)">name</span><span style="color: rgb(0,0,255)">="url"</span><span style="color: rgb(255,0,0)"> value</span><span style="color: rgb(0,0,255)">="jdbc:oracle:thin:@127.0.0.1:1521:dev"</span><span style="color: rgb(255,0,0)"> </span><span style="color: rgb(0,0,255)">/></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)"> 4</span> <span style="color: rgb(0,0,0)">        </span><span style="color: rgb(0,0,255)"><</span><span style="color: rgb(128,0,0)">property </span><span style="color: rgb(255,0,0)">name</span><span style="color: rgb(0,0,255)">="username"</span><span style="color: rgb(255,0,0)"> value</span><span style="color: rgb(0,0,255)">="kaktos"</span><span style="color: rgb(255,0,0)"> </span><span style="color: rgb(0,0,255)">/></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)"> 5</span> <span style="color: rgb(0,0,0)">        </span><span style="color: rgb(0,0,255)"><</span><span style="color: rgb(128,0,0)">property </span><span style="color: rgb(255,0,0)">name</span><span style="color: rgb(0,0,255)">="password"</span><span style="color: rgb(255,0,0)"> value</span><span style="color: rgb(0,0,255)">="kaktos"</span><span style="color: rgb(255,0,0)"> </span><span style="color: rgb(0,0,255)">/></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)"> 6</span> <span style="color: rgb(0,0,0)">    </span><span style="color: rgb(0,0,255)"></</span><span style="color: rgb(128,0,0)">bean</span><span style="color: rgb(0,0,255)">></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)"> 7</span> <span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)"> 8</span> <span style="color: rgb(0,0,0)">    </span><span style="color: rgb(0,0,255)"><</span><span style="color: rgb(128,0,0)">bean </span><span style="color: rgb(255,0,0)">id</span><span style="color: rgb(0,0,255)">="txManager"</span><span style="color: rgb(255,0,0)"><br /> </span><span style="color: rgb(0,128,128)"> 9</span> <span style="color: rgb(255,0,0)">        class</span><span style="color: rgb(0,0,255)">="org.springframework.jdbc.datasource.DataSourceTransactionManager"</span><span style="color: rgb(0,0,255)">></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)">10</span> <span style="color: rgb(0,0,0)">        </span><span style="color: rgb(0,0,255)"><</span><span style="color: rgb(128,0,0)">property </span><span style="color: rgb(255,0,0)">name</span><span style="color: rgb(0,0,255)">="dataSource"</span><span style="color: rgb(255,0,0)"> ref</span><span style="color: rgb(0,0,255)">="dataSource"</span><span style="color: rgb(255,0,0)"> </span><span style="color: rgb(0,0,255)">/></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)">11</span> <span style="color: rgb(0,0,0)">    </span><span style="color: rgb(0,0,255)"></</span><span style="color: rgb(128,0,0)">bean</span><span style="color: rgb(0,0,255)">></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)">12</span> <span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)">13</span> <span style="color: rgb(0,0,0)">    </span><span style="color: rgb(0,0,255)"><</span><span style="color: rgb(128,0,0)">bean </span><span style="color: rgb(255,0,0)">id</span><span style="color: rgb(0,0,255)">="businessBean"</span><span style="color: rgb(255,0,0)"><br /> </span><span style="color: rgb(0,128,128)">14</span> <span style="color: rgb(255,0,0)">        class</span><span style="color: rgb(0,0,255)">="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"</span><span style="color: rgb(0,0,255)">></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)">15</span> <span style="color: rgb(0,0,0)">        </span><span style="color: rgb(0,0,255)"><</span><span style="color: rgb(128,0,0)">property </span><span style="color: rgb(255,0,0)">name</span><span style="color: rgb(0,0,255)">="transactionManager"</span><span style="color: rgb(255,0,0)"> ref</span><span style="color: rgb(0,0,255)">="txManager"</span><span style="color: rgb(255,0,0)"> </span><span style="color: rgb(0,0,255)">/></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)">16</span> <span style="color: rgb(0,0,0)">        </span><span style="color: rgb(0,0,255)"><</span><span style="color: rgb(128,0,0)">property </span><span style="color: rgb(255,0,0)">name</span><span style="color: rgb(0,0,255)">="target"</span><span style="color: rgb(255,0,0)"> ref</span><span style="color: rgb(0,0,255)">="businessBeanTarget"</span><span style="color: rgb(255,0,0)"> </span><span style="color: rgb(0,0,255)">/></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)">17</span> <span style="color: rgb(0,0,0)">        </span><span style="color: rgb(0,0,255)"><</span><span style="color: rgb(128,0,0)">property </span><span style="color: rgb(255,0,0)">name</span><span style="color: rgb(0,0,255)">="transactionAttributes"</span><span style="color: rgb(0,0,255)">></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)">18</span> <span style="color: rgb(0,0,0)">            </span><span style="color: rgb(0,0,255)"><</span><span style="color: rgb(128,0,0)">props</span><span style="color: rgb(0,0,255)">></span><span style="color: rgb(0,0,0)">                <br /> </span><span style="color: rgb(0,128,128)">19</span> <span style="color: rgb(0,0,0)">                </span><span style="color: rgb(0,0,255)"><</span><span style="color: rgb(128,0,0)">prop </span><span style="color: rgb(255,0,0)">key</span><span style="color: rgb(0,0,255)">="*"</span><span style="color: rgb(0,0,255)">></span><span style="color: rgb(0,0,0)">PROPAGATION_REQUIRED</span><span style="color: rgb(0,0,255)"></</span><span style="color: rgb(128,0,0)">prop</span><span style="color: rgb(0,0,255)">></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)">20</span> <span style="color: rgb(0,0,0)">            </span><span style="color: rgb(0,0,255)"></</span><span style="color: rgb(128,0,0)">props</span><span style="color: rgb(0,0,255)">></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)">21</span> <span style="color: rgb(0,0,0)">        </span><span style="color: rgb(0,0,255)"></</span><span style="color: rgb(128,0,0)">property</span><span style="color: rgb(0,0,255)">></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)">22</span> <span style="color: rgb(0,0,0)">    </span><span style="color: rgb(0,0,255)"></</span><span style="color: rgb(128,0,0)">bean</span><span style="color: rgb(0,0,255)">></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)">23</span> <span style="color: rgb(0,0,0)">    <br /> </span><span style="color: rgb(0,128,128)">24</span> <span style="color: rgb(0,0,0)">    </span><span style="color: rgb(0,0,255)"><</span><span style="color: rgb(128,0,0)">bean </span><span style="color: rgb(255,0,0)">id</span><span style="color: rgb(0,0,255)">="businessBeanTarget"</span><span style="color: rgb(255,0,0)"> class</span><span style="color: rgb(0,0,255)">="sample.spring.trans.BusinessBean"</span><span style="color: rgb(0,0,255)">></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)">25</span> <span style="color: rgb(0,0,0)">        </span><span style="color: rgb(0,0,255)"><</span><span style="color: rgb(128,0,0)">property </span><span style="color: rgb(255,0,0)">name</span><span style="color: rgb(0,0,255)">="dataSource"</span><span style="color: rgb(255,0,0)"> ref</span><span style="color: rgb(0,0,255)">="dataSource"</span><span style="color: rgb(255,0,0)"> </span><span style="color: rgb(0,0,255)">/></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)">26</span> <span style="color: rgb(0,0,0)">    </span><span style="color: rgb(0,0,255)"></</span><span style="color: rgb(128,0,0)">bean</span><span style="color: rgb(0,0,255)">></span></font></div> <br /> q样做的弊端是不得不ؓ(f)每个需要事务的bean做一ơ声明,如果所有的bean都基本上有一致的配置Q这样就太繁琐啦?br /> 下面是第二种方式Q?br /> <div style="border-right: rgb(204,204,204) 1px solid; padding-right: 5px; border-top: rgb(204,204,204) 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: rgb(204,204,204) 1px solid; width: 98%; padding-top: 4px; border-bottom: rgb(204,204,204) 1px solid; background-color: rgb(238,238,238)"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: rgb(0,128,128)"> 1</span> <font size="1"><span style="color: rgb(0,0,255)"><</span><span style="color: rgb(128,0,0)">beans</span><span style="color: rgb(0,0,255)">></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)"> 2</span> <span style="color: rgb(0,0,0)">    </span><span style="color: rgb(0,0,255)"><</span><span style="color: rgb(128,0,0)">bean </span><span style="color: rgb(255,0,0)">id</span><span style="color: rgb(0,0,255)">="dataSource"</span><span style="color: rgb(255,0,0)"> class</span><span style="color: rgb(0,0,255)">="org.apache.commons.dbcp.BasicDataSource"</span><span style="color: rgb(255,0,0)"> destroy-method</span><span style="color: rgb(0,0,255)">="close"</span><span style="color: rgb(0,0,255)">></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)"> 3</span> <span style="color: rgb(0,0,0)">        </span><span style="color: rgb(0,0,255)"><</span><span style="color: rgb(128,0,0)">property </span><span style="color: rgb(255,0,0)">name</span><span style="color: rgb(0,0,255)">="driverClassName"</span><span style="color: rgb(255,0,0)"> value</span><span style="color: rgb(0,0,255)">="oracle.jdbc.driver.OracleDriver"</span><span style="color: rgb(255,0,0)"> </span><span style="color: rgb(0,0,255)">/></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)"> 4</span> <span style="color: rgb(0,0,0)">        </span><span style="color: rgb(0,0,255)"><</span><span style="color: rgb(128,0,0)">property </span><span style="color: rgb(255,0,0)">name</span><span style="color: rgb(0,0,255)">="url"</span><span style="color: rgb(255,0,0)"> value</span><span style="color: rgb(0,0,255)">="</span><span style="color: rgb(0,0,255)">jdbc:oracle:thin:@127.0.0.1:1521:dev</span><span style="color: rgb(0,0,255)">"</span><span style="color: rgb(255,0,0)"> </span><span style="color: rgb(0,0,255)">/></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)"> 5</span> <span style="color: rgb(0,0,0)">        </span><span style="color: rgb(0,0,255)"><</span><span style="color: rgb(128,0,0)">property </span><span style="color: rgb(255,0,0)">name</span><span style="color: rgb(0,0,255)">="username"</span><span style="color: rgb(255,0,0)"> value</span><span style="color: rgb(0,0,255)">="kaktos"</span><span style="color: rgb(255,0,0)"> </span><span style="color: rgb(0,0,255)">/></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)"> 6</span> <span style="color: rgb(0,0,0)">        </span><span style="color: rgb(0,0,255)"><</span><span style="color: rgb(128,0,0)">property </span><span style="color: rgb(255,0,0)">name</span><span style="color: rgb(0,0,255)">="password"</span><span style="color: rgb(255,0,0)"> value</span><span style="color: rgb(0,0,255)">="kaktos"</span><span style="color: rgb(255,0,0)"> </span><span style="color: rgb(0,0,255)">/></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)"> 7</span> <span style="color: rgb(0,0,0)">    </span><span style="color: rgb(0,0,255)"></</span><span style="color: rgb(128,0,0)">bean</span><span style="color: rgb(0,0,255)">></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)"> 8</span> <span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)"> 9</span> <span style="color: rgb(0,0,0)">    </span><span style="color: rgb(0,0,255)"><</span><span style="color: rgb(128,0,0)">bean </span><span style="color: rgb(255,0,0)">id</span><span style="color: rgb(0,0,255)">="txManager"</span><span style="color: rgb(255,0,0)"><br /> </span><span style="color: rgb(0,128,128)">10</span> <span style="color: rgb(255,0,0)">        class</span><span style="color: rgb(0,0,255)">="org.springframework.jdbc.datasource.DataSourceTransactionManager"</span><span style="color: rgb(0,0,255)">></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)">11</span> <span style="color: rgb(0,0,0)">        </span><span style="color: rgb(0,0,255)"><</span><span style="color: rgb(128,0,0)">property </span><span style="color: rgb(255,0,0)">name</span><span style="color: rgb(0,0,255)">="dataSource"</span><span style="color: rgb(255,0,0)"> ref</span><span style="color: rgb(0,0,255)">="dataSource"</span><span style="color: rgb(255,0,0)"> </span><span style="color: rgb(0,0,255)">/></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)">12</span> <span style="color: rgb(0,0,0)">    </span><span style="color: rgb(0,0,255)"></</span><span style="color: rgb(128,0,0)">bean</span><span style="color: rgb(0,0,255)">></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)">13</span> <span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)">14</span> <span style="color: rgb(0,0,0)">    </span><span style="color: rgb(0,0,255)"><</span><span style="color: rgb(128,0,0)">bean </span><span style="color: rgb(255,0,0)">id</span><span style="color: rgb(0,0,255)">="matchAllWithPropReq"</span><span style="color: rgb(255,0,0)"><br /> </span><span style="color: rgb(0,128,128)">15</span> <span style="color: rgb(255,0,0)">        class</span><span style="color: rgb(0,0,255)">="org.springframework.transaction.interceptor.MatchAlwaysTransactionAttributeSource"</span><span style="color: rgb(0,0,255)">></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)">16</span> <span style="color: rgb(0,0,0)">        </span><span style="color: rgb(0,0,255)"><</span><span style="color: rgb(128,0,0)">property </span><span style="color: rgb(255,0,0)">name</span><span style="color: rgb(0,0,255)">="transactionAttribute"</span><span style="color: rgb(255,0,0)"> value</span><span style="color: rgb(0,0,255)">="PROPAGATION_REQUIRED"</span><span style="color: rgb(255,0,0)"> </span><span style="color: rgb(0,0,255)">/></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)">17</span> <span style="color: rgb(0,0,0)">    </span><span style="color: rgb(0,0,255)"></</span><span style="color: rgb(128,0,0)">bean</span><span style="color: rgb(0,0,255)">></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)">18</span> <span style="color: rgb(0,0,0)">    <br /> </span><span style="color: rgb(0,128,128)">19</span> <span style="color: rgb(0,0,0)">    </span><span style="color: rgb(0,0,255)"><</span><span style="color: rgb(128,0,0)">bean </span><span style="color: rgb(255,0,0)">id</span><span style="color: rgb(0,0,255)">="matchAllTxInterceptor"</span><span style="color: rgb(255,0,0)"> class</span><span style="color: rgb(0,0,255)">="org.springframework.transaction.interceptor.TransactionInterceptor"</span><span style="color: rgb(0,0,255)">></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)">20</span> <span style="color: rgb(0,0,0)">        </span><span style="color: rgb(0,0,255)"><</span><span style="color: rgb(128,0,0)">property </span><span style="color: rgb(255,0,0)">name</span><span style="color: rgb(0,0,255)">="transactionManager"</span><span style="color: rgb(255,0,0)"> ref</span><span style="color: rgb(0,0,255)">="txManager"</span><span style="color: rgb(255,0,0)"> </span><span style="color: rgb(0,0,255)">/></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)">21</span> <span style="color: rgb(0,0,0)">        </span><span style="color: rgb(0,0,255)"><</span><span style="color: rgb(128,0,0)">property </span><span style="color: rgb(255,0,0)">name</span><span style="color: rgb(0,0,255)">="transactionAttributeSource"</span><span style="color: rgb(255,0,0)"> ref</span><span style="color: rgb(0,0,255)">="matchAllWithPropReq"</span><span style="color: rgb(255,0,0)"> </span><span style="color: rgb(0,0,255)">/></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)">22</span> <span style="color: rgb(0,0,0)">    </span><span style="color: rgb(0,0,255)"></</span><span style="color: rgb(128,0,0)">bean</span><span style="color: rgb(0,0,255)">></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)">23</span> <span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)">24</span> <span style="color: rgb(0,0,0)">    </span><span style="color: rgb(0,0,255)"><</span><span style="color: rgb(128,0,0)">bean </span><span style="color: rgb(255,0,0)">id</span><span style="color: rgb(0,0,255)">="autoProxyCreator"</span><span style="color: rgb(255,0,0)"><br /> </span><span style="color: rgb(0,128,128)">25</span> <span style="color: rgb(255,0,0)">        class</span><span style="color: rgb(0,0,255)">="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"</span><span style="color: rgb(0,0,255)">></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)">26</span> <span style="color: rgb(0,0,0)">        </span><span style="color: rgb(0,0,255)"><</span><span style="color: rgb(128,0,0)">property </span><span style="color: rgb(255,0,0)">name</span><span style="color: rgb(0,0,255)">="interceptorNames"</span><span style="color: rgb(0,0,255)">></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)">27</span> <span style="color: rgb(0,0,0)">            </span><span style="color: rgb(0,0,255)"><</span><span style="color: rgb(128,0,0)">list</span><span style="color: rgb(0,0,255)">></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)">28</span> <span style="color: rgb(0,0,0)">                </span><span style="color: rgb(0,0,255)"><</span><span style="color: rgb(128,0,0)">idref </span><span style="color: rgb(255,0,0)">local</span><span style="color: rgb(0,0,255)">="matchAllTxInterceptor"</span><span style="color: rgb(255,0,0)"> </span><span style="color: rgb(0,0,255)">/></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)">29</span> <span style="color: rgb(0,0,0)">            </span><span style="color: rgb(0,0,255)"></</span><span style="color: rgb(128,0,0)">list</span><span style="color: rgb(0,0,255)">></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)">30</span> <span style="color: rgb(0,0,0)">        </span><span style="color: rgb(0,0,255)"></</span><span style="color: rgb(128,0,0)">property</span><span style="color: rgb(0,0,255)">></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)">31</span> <span style="color: rgb(0,0,0)">        </span><span style="color: rgb(0,0,255)"><</span><span style="color: rgb(128,0,0)">property </span><span style="color: rgb(255,0,0)">name</span><span style="color: rgb(0,0,255)">="beanNames"</span><span style="color: rgb(0,0,255)">></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)">32</span> <span style="color: rgb(0,0,0)">            </span><span style="color: rgb(0,0,255)"><</span><span style="color: rgb(128,0,0)">list</span><span style="color: rgb(0,0,255)">></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)">33</span> <span style="color: rgb(0,0,0)">                </span><span style="color: rgb(0,0,255)"><</span><span style="color: rgb(128,0,0)">idref </span><span style="color: rgb(255,0,0)">local</span><span style="color: rgb(0,0,255)">="businessBean"</span><span style="color: rgb(255,0,0)"> </span><span style="color: rgb(0,0,255)">/></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)">34</span> <span style="color: rgb(0,0,0)">            </span><span style="color: rgb(0,0,255)"></</span><span style="color: rgb(128,0,0)">list</span><span style="color: rgb(0,0,255)">></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)">35</span> <span style="color: rgb(0,0,0)">        </span><span style="color: rgb(0,0,255)"></</span><span style="color: rgb(128,0,0)">property</span><span style="color: rgb(0,0,255)">></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)">36</span> <span style="color: rgb(0,0,0)">    </span><span style="color: rgb(0,0,255)"></</span><span style="color: rgb(128,0,0)">bean</span><span style="color: rgb(0,0,255)">></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)">37</span> <span style="color: rgb(0,0,0)">    <br /> </span><span style="color: rgb(0,128,128)">38</span> <span style="color: rgb(0,0,0)">    </span><span style="color: rgb(0,128,0)"><!--</span><span style="color: rgb(0,128,0)">  my beans  </span><span style="color: rgb(0,128,0)">--></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)">39</span> <span style="color: rgb(0,0,0)">    </span><span style="color: rgb(0,0,255)"><</span><span style="color: rgb(128,0,0)">bean </span><span style="color: rgb(255,0,0)">id</span><span style="color: rgb(0,0,255)">="businessBean"</span><span style="color: rgb(255,0,0)"> class</span><span style="color: rgb(0,0,255)">="sample.spring.trans.BusinessBean"</span><span style="color: rgb(0,0,255)">></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)">40</span> <span style="color: rgb(0,0,0)">        </span><span style="color: rgb(0,0,255)"><</span><span style="color: rgb(128,0,0)">property </span><span style="color: rgb(255,0,0)">name</span><span style="color: rgb(0,0,255)">="dataSource"</span><span style="color: rgb(255,0,0)"> ref</span><span style="color: rgb(0,0,255)">="dataSource"</span><span style="color: rgb(255,0,0)"> </span><span style="color: rgb(0,0,255)">/></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)">41</span> <span style="color: rgb(0,0,0)">    </span><span style="color: rgb(0,0,255)"></</span><span style="color: rgb(128,0,0)">bean</span><span style="color: rgb(0,0,255)">></span><span style="color: rgb(0,0,0)"><br /> </span><span style="color: rgb(0,128,128)">42</span> <span style="color: rgb(0,0,255)"></</span><span style="color: rgb(128,0,0)">beans</span><span style="color: rgb(0,0,255)">></span></font></div> <br /> <span style="color: rgb(0,0,255)">BeanNameAutoProxyCreator<font color="#000000">?x)在applicationcontext初始化后自动为beanNames属性中的bean建立proxy?/font></span><br /> </div> </div> </div> <img src ="http://www.tkk7.com/masen/aggbug/206269.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/masen/" target="_blank">Masen</a> 2008-06-06 11:12 <a href="http://www.tkk7.com/masen/articles/206269.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>jamonhttp://www.tkk7.com/masen/articles/172495.htmlMasenMasenThu, 03 Jan 2008 07:35:00 GMThttp://www.tkk7.com/masen/articles/172495.htmlhttp://www.tkk7.com/masen/comments/172495.htmlhttp://www.tkk7.com/masen/articles/172495.html#Feedback0http://www.tkk7.com/masen/comments/commentRss/172495.htmlhttp://www.tkk7.com/masen/services/trackbacks/172495.html  /**
*作者:(x)张荣?ahuaxuan)
*2007-8-15
*转蝲h明出处及(qing)作?
*/

前两天在看Spring内置的拦截器的时候,发现?jin)一个之前没有注意的c:(x)org.springframework.aop.interceptor.JamonPerformanceMonitorInterceptorQ好奇心(j)?j)我上|查?jin)一下这个jamon。大概看?jin)一下之后发现这个玩意还真挺好用的而且挺重要的Q而且现在国内对它的介l也很少Q所以写?jin)一文章和大家分n?

一QJamon介:(x)
Jamon的全名是QJava Application Monitor。它是一个小巧的Q免费的Q高性能的,U程安全的性能监测工具。它可以用来定pȝ的性能瓉Q也可以用来监视用户和应用程序之间的交互情况?Jamon主要是用来检jee的应用程序。它最新的版本?.1Q可以用?.4以上的jdk上?

二,jamon导入C的应用程序中?
首先下蝲jamon的开发包Q见我的附gQ同时你也可以去Sourceforge上自׃载。Sourceforge的下载地址为http://jamonapi.sourceforge.net。解压之后可以得C个jar包和一个war包。jar包是自己?x)用到的Q而war包是一个例子(不要看q个例子Q待?x)也要把它导入到目中?j)。把war包之间丢到服务器上,讉KQlocalhost:8080/jamon可以看到这个例子了(jin)Q这个例子是一个简单的性能监控pȝ?

接着把例子中的所有的包都导入到项目中Qƈ把war包中的jsp和imagesq有css都考到目中,比如新徏一个目录叫monitorQ它和W(xu)EB-INF是同U目录)(j)?

三,正确配置自己的应?
我们在性能监测的时候最监测的就是页面的讉K率和cMҎ(gu)的访问率。所以在q一部分主要讲解一下如何监自q面和类中方法的讉K?

1Q?(g)自q面讉K?
首先我们需要在web.xml中添加一个filterQ这个filter是用来判断哪些面需要被监视的,如下所C:(x)
Java代码 复制代码
  1. <filter>   
  2.         <filter-name>JAMonFilter</filter-name>   
  3.         <filter-class>com.easywebwork.filter.EasyPageMonFilter</filter-class>   
  4.     </filter>   
  5.     <filter-mapping>   
  6.         <filter-name>JAMonFilter</filter-name>   
  7.         <url-pattern>/*</url-pattern>   
  8.     </filter-mapping>  
接下来我们看看这个filter的写法:(x)
Java代码 复制代码
  1. /**  
  2.  * @author 张荣华(ahuaxuanQ? 
  3.  *  
  4.  * @since 2007-8-13  
  5.  */  
  6. public class PageMonFilter extends JAMonFilter{   
  7.   
  8.     private static final long serialVersionUID = 5746197114960908454L;   
  9.   
  10.     public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {   
  11.          Monitor allPages = MonitorFactory.start(new MonKeyImp("org.easywebwork.allPages",getURI(request),"ms."));   
  12.          //q里是我们要监视的所有的面的配|?  
  13.          Monitor monitor = MonitorFactory.start(getURI(request));   
  14.          //q里是我们要监视的某个面的配|?  
  15.          try {   
  16.           filterChain.doFilter(request, response);   
  17.          } finally {   
  18.           monitor.stop();   
  19.           allPages.stop();   
  20.          }   
  21.        }   
  22.   
  23.        protected String getURI(ServletRequest request) {   
  24.          if (request instanceof HttpServletRequest) {   
  25.            return ((HttpServletRequest) request).getRequestURI();   
  26.          }  else {   
  27.            return "Not an HttpServletRequest";   
  28.          }   
  29.        }   
  30.   
  31.        private FilterConfig filterConfig = null;   
  32.           
  33. }}  

q个cȝ上去很简单,其实也挺单的Q就是得到uriQ然后把它注册到MonitorFactorycM。这样只要我们去讉K刚才创徏的monitor目录下的jsp可以看到性能监测面?jin)?

2Q?Q接下来我们看看在用spring的情况下如何监测一个bean的方法调用。Spring也提供了(jin)对Jamon的支?spring支持的东西还真多?Q也是文章开头提出的那个拦截器,Z(jin)l我们的bean加上拦截器,我们在spring的applicationcontext配置文g中加入如下语句:(x)
Java代码 复制代码
  1. <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">   
  2.         <property name="beanNames">   
  3.             <list>   
  4.                 <value>userService</value>                 
  5.             </list>   
  6.         </property>   
  7.         <property name="interceptorNames">   
  8.             <list>   
  9.                 <value>jamonInterceptor</value>   
  10.             </list>   
  11.         </property>   
  12.     </bean>   
  13.        
  14.     <bean id="jamonInterceptor" class="org.springframework.aop.interceptor.JamonPerformanceMonitorInterceptor">   
  15. </bean>  

上面q个是典型的spring的aop的配|,如果对spring的aop配置不了(jin)解的可以ȝ一下spring中文文档Q当然如果不想了(jin)解的话即使直接把q段配置拷到自己的项目中也是可以直接使用的?

q有一个步骤就是在你的log4j.properties中加入这句代码:(x)
Java代码 复制代码
  1. log4j.logger.org.springframework.aop.interceptor.JamonPerformanceMonitorInterceptor = TRACE  

如果没有q一行,那么q个拦截器是不会(x)把方法调用的信息向MonitorFactory注册的?

只需要这些步骤,userservice中的Ҏ(gu)在调用的时候就可以被拦截,然后其注册到MonitorFactory中去?jin)?

所有的配置完成之后我们来看一下效果吧:
http://www.javaeye.com/topics/download/b2bac96e-6c18-4340-b7e0-f84c7bb6adca从这个图上我们可以看刎ͼ所有页面被讉K的次敎ͼUserService中的getAllUsers被调用的ơ数Q最双的是讉K旉。这只是整个囄一部分Q当然这个页面中也包括每一个页面被讉K的次数和W一ơ访问的旉{等。下载附件运行,可以看到所有的面?jin)?

三,ȝ
Ҏ(gu)以上的步骤,我们可以监我们的E序?jin),应用E序中哪些页面被讉K的多Q哪些页面被讉K的少Q哪些方法被讉K的多Q哪些方法被讉K的少Q以?qing)访问高峰期集中在什么时间等{,有了(jin)q些参数Q我们更可以有针Ҏ(gu)的对应用程序进行优化了(jin)Q比如说某个面讉K比较频繁Q我可以用ehcache或oscachel这个页面做一个缓存。如果某个方法的讉K比较频繁那就看看q个Ҏ(gu)能否q一步优化,是需要异步,q是需要缓存,q是需要其他等{,M有了(jin)jamon可以l我们带来更多的便捷Q既可以让我们知道我们的客户的行为,也可以让我们知道我们开发的E序?#8220;能力”?

其实本文提供的只是对面和方法调用的监控Q但是jamon可以提供更多功能Q比如说sql语句的监控等{,q就需要我们共同去发掘?jin)?

附g中包括了(jin)一个easywebwork的例子,我把jamon导入到这个例子工E中去,大家可以直接下蝲q行观看效果。Easywebwork是一个旨在减webwork2.2.xpd的xml配置文g的项目,
如果对这个主题感兴趣请到
http://www.javaeye.com/topic/91614
http://www.javaeye.com/topic/93814
参加讨论?


Masen 2008-01-03 15:35 发表评论
]]>
Spring 中的数据?/title><link>http://www.tkk7.com/masen/articles/118701.html</link><dc:creator>Masen</dc:creator><author>Masen</author><pubDate>Sun, 20 May 2007 08:40:00 GMT</pubDate><guid>http://www.tkk7.com/masen/articles/118701.html</guid><wfw:comment>http://www.tkk7.com/masen/comments/118701.html</wfw:comment><comments>http://www.tkk7.com/masen/articles/118701.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.tkk7.com/masen/comments/commentRss/118701.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/masen/services/trackbacks/118701.html</trackback:ping><description><![CDATA[     摘要: 1、用Spring自带的DriverManagerDataSource   配置文g <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"  "http://www.springframework.org/dtd/...  <a href='http://www.tkk7.com/masen/articles/118701.html'>阅读全文</a><img src ="http://www.tkk7.com/masen/aggbug/118701.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/masen/" target="_blank">Masen</a> 2007-05-20 16:40 <a href="http://www.tkk7.com/masen/articles/118701.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://www.tkk7.com/" title="亚洲av成人片在线观看">亚洲av成人片在线观看</a> <div class="friend-links"> </div> </div> </footer> վ֩ģ壺 <a href="http://wwwy66y6.com" target="_blank">޹ƷۺϾþ</a>| <a href="http://maomi90.com" target="_blank">ɫַѹۿ</a>| <a href="http://fsweicheng.com" target="_blank">þerƷѹۿ8</a>| <a href="http://wwwks2424.com" target="_blank">ŮƵƵȫƵ</a>| <a href="http://sdcwpfw.com" target="_blank">ҹҹAһ</a>| <a href="http://schygfz.com" target="_blank">ۺ߹ۿ</a>| <a href="http://wlamyx.com" target="_blank">þþƷ뾫Ʒר</a>| <a href="http://jyd56.com" target="_blank">?V˾Ʒպ</a>| <a href="http://appmofun.com" target="_blank">þþƷAVɫ</a>| <a href="http://xyflash.com" target="_blank">baoyu777Ƶ </a>| <a href="http://aicbbs.com" target="_blank">ҹAVպAVȫ</a>| <a href="http://yidazn.com" target="_blank">˳ɶ߲r18</a>| <a href="http://10242016.com" target="_blank">ëƬŮAPP </a>| <a href="http://fense1.com" target="_blank">޾ƷĻAƬ</a>| <a href="http://lyczyb.com" target="_blank">߹ۿavվ</a>| <a href="http://www961dd.com" target="_blank">ŷղþ99 </a>| <a href="http://boyonet.com" target="_blank">žۺVAѿ</a>| <a href="http://wwwhaole10.com" target="_blank">ҹƵѳ</a>| <a href="http://bobostrong31.com" target="_blank">޵һվȫ</a>| <a href="http://33eaa.com" target="_blank">պAVһ</a>| <a href="http://yx6768.com" target="_blank">޾Ʒ</a>| <a href="http://chuadang.com" target="_blank">99þùۺϾƷ</a>| <a href="http://wwwayx2026.com" target="_blank">99Ƶۿ</a>| <a href="http://xuanzhicity.com" target="_blank">츾avһ</a>| <a href="http://222mp3.com" target="_blank">뾫Ʒһ</a>| <a href="http://h7277.com" target="_blank">պƷһ</a>| <a href="http://91packing.com" target="_blank">Ʒ޹</a>| <a href="http://fuzhiwushu.com" target="_blank">ѹۿ</a>| <a href="http://344zx.com" target="_blank">þAV</a>| <a href="http://xa69.com" target="_blank">һƬaѲſ</a>| <a href="http://www961dd.com" target="_blank">պƷһ</a>| <a href="http://8833081.com" target="_blank">ҹӰ</a>| <a href="http://sk7758.com" target="_blank">ëƬѹۿ</a>| <a href="http://dwj28.com" target="_blank">99|</a>| <a href="http://www33399.com" target="_blank">Ƶ</a>| <a href="http://pjwys.com" target="_blank">ۺϼƵ</a>| <a href="http://gg596gg.com" target="_blank">ĻӰȫѰ </a>| <a href="http://www66913.com" target="_blank">Ļ߲Ƶ</a>| <a href="http://taoh2510.com" target="_blank">ҸŮˬ߳Ƭ </a>| <a href="http://wwwbu610.com" target="_blank">޹Ƭ߹ۿ </a>| <a href="http://xx9911.com" 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>