??xml version="1.0" encoding="utf-8" standalone="yes"?>国产精品亚洲一区二区在线观看,亚洲AV永久无码精品一区二区国产
,亚洲乱码精品久久久久.. http://www.tkk7.com/masen/category/22616.htmlzh-cn Thu, 26 Mar 2015 17:29:25 GMT Thu, 26 Mar 2015 17:29:25 GMT 60 Spring事务理器的应对 (? http://www.tkk7.com/masen/articles/423831.htmlMasen Masen Wed, 25 Mar 2015 10:07:00 GMT http://www.tkk7.com/masen/articles/423831.html http://www.tkk7.com/masen/comments/423831.html http://www.tkk7.com/masen/articles/423831.html#Feedback 0 http://www.tkk7.com/masen/comments/commentRss/423831.html http://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> 1 Hibernate+ Spring JDBC或iBatis org.springframework.orm.hibernate3.HibernateTransactionManager 2 JPA+Spring JDBC或iBatis org.springframework.orm.jpa.JpaTransactionManager 3 JDO+Spring JDBC或iBatis org.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代码
package com.baobaotao.mixdao; … @Service ("userService") public class UserService extends BaseService { @Autowired private HibernateTemplate hibernateTemplate; @Autowired private ScoreService scoreService; public void logon(String userName) { //①通过Hibernate技术访问数?/span> System.out.println("before updateLastLogonTime().."); updateLastLogonTime(userName); System.out.println("end updateLastLogonTime().."); //②通过JDBC技术访问数?/span> System.out.println("before scoreService.addScore().."); scoreService.addScore(userName, 20 ); System.out.println("end scoreService.addScore().."); } public void updateLastLogonTime(String userName) { User user = hibernateTemplate.get(User.class ,userName); user.setLastLogonTime(System.currentTimeMillis()); hibernateTemplate.update(user); //③q句很重要,L(fng)下文的分?/span> hibernateTemplate.flush(); } } ?#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代码
package com.baobaotao.mixdao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; import org.apache.commons.dbcp.BasicDataSource; @Service ("scoreService") public class ScoreService extends BaseService{ @Autowired private JdbcTemplate jdbcTemplate; public void addScore(String userName, int toAdd) { String sql = "UPDATE t_user u SET u.score = u.score + ? WHERE user_name =?"; jdbcTemplate.update(sql, toAdd, userName); BasicDataSource basicDataSource = (BasicDataSource) jdbcTemplate.getDataSource(); //①查看此处数据库激zȝq接数量 System.out.println("[scoreUserService.addScore]Ȁz连接数量:(x)" +basicDataSource.getNumActive()); } } Spring关键的配|文件代码如下所C:(x) Xml代码
… <!--①使用Hibernate事务理?nbsp;--> < bean id ="hiberManager" class ="org.springframework.orm.hibernate3.HibernateTransactionManager" p:sessionFactory-ref ="sessionFactory" /> <!--②使UserService?qing)ScoreService的公用方法都拥有事务 --> < aop:config proxy-target-class ="true" > < aop:pointcut id ="serviceJdbcMethod" expression ="within(com.baobaotao.mixdao.BaseService+)" /> < aop:advisor pointcut-ref ="serviceJdbcMethod" advice-ref ="hiberAdvice" /> </ aop:config > < tx:advice id ="hiberAdvice" transaction-manager ="hiberManager" > < tx:attributes > < tx:method name ="*" /> </ tx:attributes > </ tx:advice > /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; ]]>Spring声明式事务管理与配置详解(? http://www.tkk7.com/masen/articles/423824.htmlMasen Masen Wed, 25 Mar 2015 07:48:00 GMT http://www.tkk7.com/masen/articles/423824.html http://www.tkk7.com/masen/comments/423824.html http://www.tkk7.com/masen/articles/423824.html#Feedback 0 http://www.tkk7.com/masen/comments/commentRss/423824.html http://www.tkk7.com/masen/services/trackbacks/423824.html 阅读全文 ]]> cron 表达式的格式 (转http://www.tkk7.com/Unmi/archive/2008/02/23/181575.htmlQ作者:(x)隔叶黄莺) http://www.tkk7.com/masen/articles/208816.htmlMasen Masen Wed, 18 Jun 2008 03:44:00 GMT http://www.tkk7.com/masen/articles/208816.html http://www.tkk7.com/masen/comments/208816.html http://www.tkk7.com/masen/articles/208816.html#Feedback 0 http://www.tkk7.com/masen/comments/commentRss/208816.html http://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>域上?SEP Q那?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如果是15W Q可能会(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#3 Q它意思是某月的第三个周五 (6 =星期五,#3 意味着月䆾中的W三?。另一个例?2#1 意思是某月的第一个星期一 (2 =星期一Q?font color="#800080">#1 意味着月䆾中的W一?。注意,假如你指?#5 Q然而月份中没有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>
]]> 详解spring事务属?? http://www.tkk7.com/masen/articles/208548.htmlMasen Masen Tue, 17 Jun 2008 03:02:00 GMT http://www.tkk7.com/masen/articles/208548.html http://www.tkk7.com/masen/comments/208548.html http://www.tkk7.com/masen/articles/208548.html#Feedback 0 http://www.tkk7.com/masen/comments/commentRss/208548.html http://www.tkk7.com/masen/services/trackbacks/208548.html Spring声明式事务让我们从复杂的事务处理中得到解脱。得我们再也无需要去处理获得q接、关闭连接、事务提交和回滚{这些操作。再也无需要我们在与事务相关的Ҏ(gu)中处理大量的try…catch…finally代码?
我们在用Spring声明式事务时Q有一个非帔R要的概念是事务属性。事务属性通常׃务的传播行ؓ(f)Q事务的隔离U别Q事务的时值和事务只读标志l成。我们在q行事务划分Ӟ需要进行事务定义,也就是配|事务的属性?
Spring?strong>TransactionDefinition接口中定义这些属?以供PlatfromTransactionManager使用, PlatfromTransactionManager是spring事务理的核?j)接口?
代码
TransactionDefinition
public interface TransactionDefinition {
int getPropagationBehavior();
int getIsolationLevel();
int getTimeout();
boolean isReadOnly();
}
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但未提交事?
代码
Connection con1 = getConnection();
con.setAutoCommit( false );
update employee set salary = 8000 where empId = "Mary" ;
与此同时QMary正在d自己的工?
代码
Connection con2 = getConnection();
select salary from employee where empId = "Mary" ;
con2.commit();
Mary发现自己的工资变Z(jin)8000Q欢天喜圎ͼ
而胦(ch)务发现操作有误,而回滚了(jin)事务,Mary的工资又变ؓ(f)?000
代码
像这?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没有完?
代码
con1 = getConnection();
select salary from employee empId = "Mary" ;
在事?中,q时财务人员修改?jin)Mary的工资ؓ(f)2000,q提交了(jin)事务.
代码
con2 = getConnection();
update employee set salary = 2000 ;
con2.commit();
在事?中,Mary 再次d自己的工资时Q工资变Z(jin)2000
代码
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的员工?
代码
con1 = getConnection();
Select * from employee where salary = 1000 ;
p?0条记?
q时另一个事务向employee表插入了(jin)一条员工记录,工资也ؓ(f)1000
代码
con2 = getConnection();
Insert into employee(empId,salary) values( "Lili" , 1000 );
con2.commit();
事务1再次d所有工资ؓ(f)1000的员?
代码
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>
代码
methodA{
……
methodB();
……
}
methodB{
……
}
使用spring声明式事务,spring使用AOP来支持声明式事务Q会(x)Ҏ(gu)事务属性,自动在方法调用之前决定是否开启一个事务,q在Ҏ(gu)执行之后军_事务提交或回滚事务?
单独调用methodBҎ(gu)
代码
相当?
代码
Main{
Connection con= null ;
rry{
con = getConnection();
con.setAutoCommit( false );
methodB();
con.commit();
}
Catch(RuntimeException ex){
con.rollback();
}
finally {
closeCon();
}
}
Spring保证在methodBҎ(gu)中所有的调用都获得到一个相同的q接。在调用methodBӞ没有一个存在的事务Q所以获得一个新的连接,开启了(jin)一个新的事务?
单独调用MethodAӞ在MethodA内又?x)调用MethodB.
执行效果相当?
代码
main{
Connection con = null ;
try {
con = getConnection();
methodA();
con.commit();
}
cathc(RuntimeException ex){
con.rollback();
}
finally {
closeCon();
}
}
调用MethodAӞ环境中没有事务,所以开启一个新的事?
当在MethodA中调用MethodBӞ环境中已l有?jin)一个事务,所以methodB加入当前事务?
PROPAGATION_SUPPORTS 如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行。但是对于事务同步的事务理器,PROPAGATION_SUPPORTS与不使用事务有少怸同?/p>
代码
methodA(){
methodB();
}
methodB(){
……
}
单纯的调用methodBӞmethodBҎ(gu)是非事务的执行的?
当调用methdA?methodB则加入了(jin)methodA的事务中,事务地执行?
PROPAGATION_MANDATORY 如果已经存在一个事务,支持当前事务。如果没有一个活动的事务Q则抛出异常?/p>
代码
methodA(){
methodB();
}
methodB(){
……
}
当单独调用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>
代码
methodA(){
doSomeThingA();
methodB();
doSomeThingB();
}
methodB(){
……
}
当单独调用methodBӞ相当于把methodb声明为REQUIRED。开启一个新的事务,事务地执行?
当调用methodA?
代码
情况有些大不一?相当于下面的效果?
代码
main(){
TransactionManager tm = null ;
try {
tm = getTransactionManager();
tm.begin();
Transaction ts1 = tm.getTransaction();
doSomeThing();
tm.suspend();
try {
tm.begin();
Transaction ts2 = tm.getTransaction();
methodB();
ts2.commit();
}
Catch(RunTimeException ex){
ts2.rollback();
}
finally {
}
tm.resume(ts1);
doSomeThingB();
ts1.commit();
}
catch (RunTimeException ex){
ts1.rollback();
}
finally {
}
}
在这里,我把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>
代码
methodA(){
doSomeThingA();
methodB();
doSomeThingB();
}
methodB(){
……
}
当单独调用methodBӞ不启用Q何事务机Ӟ非事务地执行?
当调用methodAӞ相当于下面的效果
代码
main(){
TransactionManager tm = null ;
try {
tm = getTransactionManager();
tm.begin();
Transaction ts1 = tm.getTransaction();
doSomeThing();
tm.suspend();
methodB();
tm.resume(ts1);
doSomeThingB();
ts1.commit();
}
catch (RunTimeException ex){
ts1.rollback();
}
finally {
}
}
使用PROPAGATION_NOT_SUPPORTED,也需要用JtaTransactionManager作ؓ(f)事务理器?
PROPAGATION_NEVER L非事务地执行Q如果存在一个活动事务,则抛出异?/p>
代码
methodA(){
doSomeThingA();
methodB();
doSomeThingB();
}
methodB(){
……
}
单独调用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;
代码
methodA(){
doSomeThingA();
methodB();
doSomeThingB();
}
methodB(){
……
}
如果单独调用methodBҎ(gu)Q则按REQUIRED属性执行?
如果调用methodAҎ(gu)Q相当于下面的效?
代码
main(){
Connection con = null ;
Savepoint savepoint = null ;
try {
con = getConnection();
con.setAutoCommit( false );
doSomeThingA();
savepoint = con2.setSavepoint();
try
methodB();
} catch (RuntimeException ex){
con.rollback(savepoint);
}
finally {
}
doSomeThingB();
con.commit();
}
catch (RuntimeException ex){
con.rollback();
}
finally {
}
}
当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>
]]>spring事务相关Q{Q?/title> http://www.tkk7.com/masen/articles/206269.htmlMasen Masen Fri, 06 Jun 2008 03:12:00 GMT http://www.tkk7.com/masen/articles/206269.html http://www.tkk7.com/masen/comments/206269.html http://www.tkk7.com/masen/articles/206269.html#Feedback 0 http://www.tkk7.com/masen/comments/commentRss/206269.html http://www.tkk7.com/masen/services/trackbacks/206269.html spring事务理
通常通过TransactionProxyFactoryBean讄Spring事务代理。我们需要一个目标对象包装在事务代理中。这个目标对象一般是一个普通Java对象的bean。当我们定义TransactionProxyFactoryBeanӞ必须提供一个相关的 PlatformTransactionManager的引用和
事务属?/strong>?事务属?/strong>含有上面描述的事务定义?
<bean id="petStore"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager"><ref bean="transactionManager"/></property>
<property name="target"><ref bean="petStoreTarget"/></property>
<property name="transactionAttributes">
<props>
<prop key="insert*">PROPAGATION_REQUIRED,-MyCheckedException</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
事务代理?x)实现目标对象的接口Q这里是id为petStoreTarget的bean。(使用 CGLIB也可以实现具体类的代理。只要设|proxyTargetClass属性ؓ(f)true可以。如果目标对象没有实CQ何接口,q将自动讄该属性ؓ(f)true。通常Q我们希望面向接口而不是类~程。)(j)使用proxyInterfaces属性来限定事务代理来代 理指定接口也是可以的 Q一般来说是个好xQ。也可以通过?org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource 中的属性格式来讄。这个包括通配W的Ҏ(gu)名称映射是很直观的。注?insert*的映的值包括回滚规则。添加的MyCheckedException 或它的子c,事务??x)自动回滚。可以用逗号分隔定义多个回滚规则?font color="#ff0000">-前缀强制回滚Q?前缀指定提交 Q这允许即抛出unchecked异常时也可以提交事务Q当然你自己要明白自?在做什么)(j)?/p>
Advisor Q可以包含一个切入点Q, ThrowAdvice Q?BeforeAdvice Q?q些都是默认支持的)(j)。这些通知必须支持实例׃n模式。如果你需要高UAOP?性来使用事务Q如有状态的maxinQ那最好用通用?TransactionProxyFactoryBean 实用代理创徏者?/p>
也可以设|自动代理:(x)配置AOP框架Q不需要单独的代理定义cd可以生成cȝ 代理?/p>
附两个spring的事务配|例子:(x)
<prop key="add">
PROPAGATION_REQUIRES_NEW, -MyException
</prop>
注:(x)上面的意思是addҎ(gu)独占一个事务,当事务处理过E中产生MyException异常或者该异常的子cd回滚该事务?br />
<prop key="loadAll">
PROPAGATION_SUPPORTS, ISOLATION_READ_COMMITED, Readonly
</prop>
注:(x)表示loadAllҎ(gu)支持事务Q而且不会(x)d没有提交事务的数据。它的数据ؓ(f)只读Q这h助于提高d的性能Q?br />
附A Spring中的所有事务策?br />
PROPAGATION_MANDATORY
PROPAGATION_NESTED
PROPAGATION_NEVER
PROPAGATION_NOT_SUPPORTED
PROPAGATION_REQUIRED
PROPAGATION_REQUIRED_NEW
PROPAGATION_SUPPORTS
附B Spring中所有的隔离{略Q?br />
ISOLATION_DEFAULT
ISOLATION_READ_UNCOMMITED
ISOLATION_COMMITED
ISOLATION_REPEATABLE_READ
ISOLATION_SERIALIZABLE
Spring事务cd解
大家可能在spring中经常看到这L(fng)定义Q?/p>
<prop key="load*">PROPAGATION_REQUIRED,readOnly</prop><prop key="store*">PROPAGATION_REQUIRED</prop>
估计有好多朋友还没有弄清楚里面的值的意思,仔细看完下面应该知道自己什么情况下面应该用什么样的声明。^_^
Spring中常用事务类型:(x)
PROPAGATION_REQUIRED--支持当前事务Q如果当前没有事务,新Z个事务。这是最常见的选择?
PROPAGATION_SUPPORTS--支持当前事务Q如果当前没有事务,׃非事务方式执行?
PROPAGATION_MANDATORY--支持当前事务Q如果当前没有事务,抛出异常?
PROPAGATION_REQUIRES_NEW--新徏事务Q如果当前存在事务,把当前事务挂赗?
PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作Q如果当前存在事务,把当前事务挂v?
PROPAGATION_NEVER--以非事务方式执行Q如果当前存在事务,则抛出异常?
PROPAGATION_NESTED--如果当前存在事务Q则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIREDcM的操作?br />
摘要Q?br />
Spring和EJB一P提供?jin)两U事务管理方式:(x)~程式和声明式。在考试pȝ中我们将使用声明式的事务理Q这是spring推荐的做法。用这U方式可以体验到spring的强大便P而且我们无须在DaocM~写MҎ(gu)的代码,只需要通过配置文g可以让普通的javacd载到事务理中,q个意义是很重大的?
本文Matrix怹镜像Q?a >http://www.matrix.org.cn/resource/article/1/1339.html
说明Q本文可能由Matrix原创Q也可能由Matrix的会(x)员整理,或者由
Matrix的Crawler在全球知名Java或者其他技术相关站Ҏ(gu)取ƈ怹
保留镜像QMatrix?x)保留所有原来的出处URLQƈ在显著地方作?gu)明?br />
如果你发觉出处URL有误Q请联系MatrixҎ(gu).
四、Spring中的事务控制
Spring和EJB一P提供?jin)两U事务管理方式:(x)~程式和声明式。在考试pȝ中我们将使用声明式的事务理Q这是spring推荐的做法。用这U方式可以体验到spring的强大便P而且我们无须在DaocM~写MҎ(gu)的代码,只需要通过配置文g可以让普通的javacd载到事务理中,q个意义是很重大的?br />
Spring中进行事务管理的通常方式是利用AOPQ面向切片编E)(j)的方式,为普通javacd装事务控Ӟ它是通过动态代理实现的Q由于接口是延迟实例化的Qspring在这D|间内通过拦截器,加蝲事务切片。原理就是这P具体l节请参考jdk中有兛_态代理的文档。本文主要讲解如何在spring中进行事务控制?br />
动态代理的一个重要特征是Q它是针Ҏ(gu)口的Q所以我们的dao要通过动态代理来让spring接管事务Q就必须在dao前面抽象Z个接口,当然如果没有q样的接口,那么spring?x)用CGLIB来解决问题,但这不是spring推荐的方式,我们也不做讨论?br />
参照前面的例子,我们为StudentManager.java定义一个接口,它的内容如下Q?br />
/*
* 创徏日期 2005-3-25
*/
package org.bromon.spring.examer.student;
import java.util.List;
import org.bromon.spring.examer.pojo.Student;
/**
* @author Bromon
*/
public interface StudentManagerInterface
{
public void add(Student s);
public void del(Student s);
public void update(Student s);
public List loadAll();
public Student loadById(int id);
}
StudentManager也应该做Z改,实现该接口:(x)
public class StudentManager extends HibernateDaoSupport implements StudentManagerInterface
现在需要修攚w|文Ӟ用于定义Hibrenate适用的事务管理器Qƈ且把sessionFactory注入q去Q同时还需要通过注册一个DefaultTransactionAttribute对象Q来指出事务{略。其中sessionFactory的定义已l在本文的第三章中说明?br />
首先定义一个Hibernate的事务管理器Q让它来理sessionFactoryQ?br />
<bean id="transactionManager" class="org.springframework.orm.hibernate.HibernateTransactionManager">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>
下面定义事务理{略Q我们希望把{略定义在方法这个别上Q提供最大的灉|性,本例中将addҎ(gu)定义为:(x)PROPAGATION_REQUIRES_NEWQ这可以保证它将始终q行在一个事务中?br />
<bean id="transactionAttributeSource" class="org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource">
<property name="properties">
<props>
<prop key="add">
PROPAGATION_REQUIRES_NEW
</prop>
</props>
</property>
</bean>
我们不仅可以为addҎ(gu)定义事务{略,q可以定义事务隔ȝ度和回滚{略,他们以逗号隔开,比如我们的add事务可以定义?
<prop key="add">
PROPAGATION_REQUIRES_NEW,-ExamerException
</prop
>
q个事务{略表示addҎ(gu)会(x)独占一个事务,当事务过E中产生ExamerException异常Q事务会(x)回滚?br />
Add/update/del都是写入Ҏ(gu)Q对于selectQ读取)(j)Ҏ(gu)Q我们可以指定较为复杂的事务{略Q比如对于loadAll()Ҏ(gu)Q?br />
<prop key=”loadAll”>
PROPAGATION_SUPPORTS,ISOLATION_READ_COMMITED,readOnly
</prop>
该事务的含义为,loadAllҎ(gu)支持事务Q不?x)读M提交的数据,它的数据为只读(可提高执行速度Q?br />
如你所见,我们的StudentManagerInterface接口中还有一个loadById(int id)Ҏ(gu)Q也许我们将来还?x)有很多的loadByXXXX的方法,N要意义ؓ(f)他们指定事务{略Q太?ch)h?jin),他们应该和loadAll()一P所以我们可以用通配W,定义所有的loadXXXXҎ(gu)Q?br />
<prop key=”load*”>
PROPAGATION_SUPPORTS,ISOLATION_READ_COMMITED,readOnly
</prop>
现在可以定义事务理器:(x)
<bean id="studentManager" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="target">
<ref bean="studentManager"/>
</property>
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property name="transactionAttributeSource">
<ref bean="transactionAttributeSource"/>
</property>
</bean>
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)
public void testAdd()
{
ApplicationContext ctx=new ClassPathXmlApplicationContext("springConfig.xml");
StudentManager sm=(StudentManager)ctx.getBean("studentManager");
Student s=new Student();
s.setId(1);
s.setName("bromon");
s.setPassword("123");
s.setGrade(1);
s.setSex(0);
sm.add(s);
}
通过以上的代码可以看出,spring可以单的把普通的java classU_事务理Q声明性的事务操作h也很Ҏ(gu)。有?jin)spring之后Q声明性事务不再是EJB独有Q我们不必ؓ(f)?jin)获得声明性事务的功能而去忍受EJB带来的种U不ѝ?br />
我所使用的mysql是不支持事务的,你可以更换用PostgreSQLQ有?jin)spring+hibernateQ更换dbq不像以前那h怖了(jin)Q步骤很单:(x)
1?dPostgreSQL的jdbc驱动
2?修改dataSource配置Q包括驱动名U、url、帐受密?br />
3?修改sessionFactory的数据库dailet为net.sf.hibernate.dialect.PostgreSQLDialect
4?修改hbm.xml中的主键生成{略为increment
所有的修改都在配置文g中完成,业务代码不需要Q何修改,我很满意QHow about u?
传统的:(x)
1 < bean id ="dataSource" class ="org.apache.commons.dbcp.BasicDataSource" destroy-method ="close" >
2 < property name ="driverClassName" value ="oracle.jdbc.driver.OracleDriver" />
3 < property name ="url" value ="jdbc:oracle:thin:@127.0.0.1:1521:dev" />
4 < property name ="username" value ="kaktos" />
5 < property name ="password" value ="kaktos" />
6 </ bean >
7
8 < bean id ="txManager"
9 class ="org.springframework.jdbc.datasource.DataSourceTransactionManager" >
10 < property name ="dataSource" ref ="dataSource" />
11 </ bean >
12
13 < bean id ="businessBean"
14 class ="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" >
15 < property name ="transactionManager" ref ="txManager" />
16 < property name ="target" ref ="businessBeanTarget" />
17 < property name ="transactionAttributes" >
18 < props >
19 < prop key ="*" > PROPAGATION_REQUIRED </ prop >
20 </ props >
21 </ property >
22 </ bean >
23
24 < bean id ="businessBeanTarget" class ="sample.spring.trans.BusinessBean" >
25 < property name ="dataSource" ref ="dataSource" />
26 </ bean >
q样做的弊端是不得不ؓ(f)每个需要事务的bean做一ơ声明,如果所有的bean都基本上有一致的配置Q这样就太繁琐啦?br />
下面是第二种方式Q?br />
1 < beans >
2 < bean id ="dataSource" class ="org.apache.commons.dbcp.BasicDataSource" destroy-method ="close" >
3 < property name ="driverClassName" value ="oracle.jdbc.driver.OracleDriver" />
4 < property name ="url" value =" jdbc:oracle:thin:@127.0.0.1:1521:dev " />
5 < property name ="username" value ="kaktos" />
6 < property name ="password" value ="kaktos" />
7 </ bean >
8
9 < bean id ="txManager"
10 class ="org.springframework.jdbc.datasource.DataSourceTransactionManager" >
11 < property name ="dataSource" ref ="dataSource" />
12 </ bean >
13
14 < bean id ="matchAllWithPropReq"
15 class ="org.springframework.transaction.interceptor.MatchAlwaysTransactionAttributeSource" >
16 < property name ="transactionAttribute" value ="PROPAGATION_REQUIRED" />
17 </ bean >
18
19 < bean id ="matchAllTxInterceptor" class ="org.springframework.transaction.interceptor.TransactionInterceptor" >
20 < property name ="transactionManager" ref ="txManager" />
21 < property name ="transactionAttributeSource" ref ="matchAllWithPropReq" />
22 </ bean >
23
24 < bean id ="autoProxyCreator"
25 class ="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator" >
26 < property name ="interceptorNames" >
27 < list >
28 < idref local ="matchAllTxInterceptor" />
29 </ list >
30 </ property >
31 < property name ="beanNames" >
32 < list >
33 < idref local ="businessBean" />
34 </ list >
35 </ property >
36 </ bean >
37
38 <!-- my beans -->
39 < bean id ="businessBean" class ="sample.spring.trans.BusinessBean" >
40 < property name ="dataSource" ref ="dataSource" />
41 </ bean >
42 </ beans >
BeanNameAutoProxyCreator?x)在applicationcontext初始化后自动为beanNames属性中的bean建立proxy?/font>
]]> jamon http://www.tkk7.com/masen/articles/172495.htmlMasen Masen Thu, 03 Jan 2008 07:35:00 GMT http://www.tkk7.com/masen/articles/172495.html http://www.tkk7.com/masen/comments/172495.html http://www.tkk7.com/masen/articles/172495.html#Feedback 0 http://www.tkk7.com/masen/comments/commentRss/172495.html http://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)
<filter>
<filter-name>JAMonFilter</filter-name>
<filter- class >com.easywebwork.filter.EasyPageMonFilter</filter- class >
</filter>
<filter-mapping>
<filter-name>JAMonFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>JAMonFilter</filter-name>
<filter-class>com.easywebwork.filter.EasyPageMonFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>JAMonFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
接下来我们看看这个filter的写法:(x)
public class PageMonFilter extends JAMonFilter{
private static final long serialVersionUID = 5746197114960908454L;
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
Monitor allPages = MonitorFactory.start( new MonKeyImp( "org.easywebwork.allPages" ,getURI(request), "ms." ));
Monitor monitor = MonitorFactory.start(getURI(request));
try {
filterChain.doFilter(request, response);
} finally {
monitor.stop();
allPages.stop();
}
}
protected String getURI(ServletRequest request) {
if (request instanceof HttpServletRequest) {
return ((HttpServletRequest) request).getRequestURI();
} else {
return "Not an HttpServletRequest" ;
}
}
private FilterConfig filterConfig = null ;
}}
/**
* @author 张荣华(ahuaxuanQ?
*
* @since 2007-8-13
*/
public class PageMonFilter extends JAMonFilter{
private static final long serialVersionUID = 5746197114960908454L;
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
Monitor allPages = MonitorFactory.start(new MonKeyImp("org.easywebwork.allPages",getURI(request),"ms."));
//q里是我们要监视的所有的面的配|?
Monitor monitor = MonitorFactory.start(getURI(request));
//q里是我们要监视的某个面的配|?
try {
filterChain.doFilter(request, response);
} finally {
monitor.stop();
allPages.stop();
}
}
protected String getURI(ServletRequest request) {
if (request instanceof HttpServletRequest) {
return ((HttpServletRequest) request).getRequestURI();
} else {
return "Not an HttpServletRequest";
}
}
private FilterConfig filterConfig = null;
}}
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)
<bean class = "org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator" >
<property name= "beanNames" >
<list>
<value>userService</value>
</list>
</property>
<property name= "interceptorNames" >
<list>
<value>jamonInterceptor</value>
</list>
</property>
</bean>
<bean id= "jamonInterceptor" class = "org.springframework.aop.interceptor.JamonPerformanceMonitorInterceptor" >
</bean>
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames">
<list>
<value>userService</value>
</list>
</property>
<property name="interceptorNames">
<list>
<value>jamonInterceptor</value>
</list>
</property>
</bean>
<bean id="jamonInterceptor" class="org.springframework.aop.interceptor.JamonPerformanceMonitorInterceptor">
</bean>
上面q个是典型的spring的aop的配|,如果对spring的aop配置不了(jin)解的可以ȝ一下spring中文文档Q当然如果不想了(jin)解的话即使直接把q段配置拷到自己的项目中也是可以直接使用的?
q有一个步骤就是在你的log4j.properties中加入这句代码:(x)
log4j.logger.org.springframework.aop.interceptor.JamonPerformanceMonitorInterceptor = TRACE
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
参加讨论?
]]> Spring 中的数据?/title> http://www.tkk7.com/masen/articles/118701.htmlMasen Masen Sun, 20 May 2007 08:40:00 GMT http://www.tkk7.com/masen/articles/118701.html http://www.tkk7.com/masen/comments/118701.html http://www.tkk7.com/masen/articles/118701.html#Feedback 2 http://www.tkk7.com/masen/comments/commentRss/118701.html http://www.tkk7.com/masen/services/trackbacks/118701.html 阅读全文 ]]>
վ֩ģ壺
ƷۺϾþ |
ɫַѹۿ |
þerƷѹۿ8 |
ŮƵƵȫƵ |
ҹҹAһ |
ۺ߹ۿ |
þþƷ뾫Ʒר |
?V˾Ʒպ |
þþƷAVɫ |
baoyu777Ƶ
|
ҹAVպAVȫ |
˳ɶ߲r18 |
ëƬŮAPP
|
ƷĻAƬ |
߹ۿavվ |
ŷղþ99
|
žۺVAѿ |
ҹƵѳ |
һվȫ |
պAVһ |
Ʒ |
99þùۺϾƷ |
99Ƶۿ |
츾avһ |
뾫Ʒһ |
պƷһ |
Ʒ |
ѹۿ |
þAV |
һƬaѲſ |
պƷһ |
ҹӰ |
ëƬѹۿ |
99| |
Ƶ |
ۺϼƵ |
ĻӰȫѰ
|
Ļ߲Ƶ |
ҸŮˬ߳Ƭ
|
Ƭ߹ۿ
|
ĻŮ |