<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>杨振</title>
    <description></description>
    <link>http://yangzhen.javaeye.com</link>
    <language>UTF-8</language>
    <copyright>Copyright 2003-2008, JavaEye.com</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>JavaEye - 做最棒的软件开发交流社区</generator>
      <item>
        <title>easymock求助</title>
        <author>yz_beijing</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://yangzhen.javaeye.com">yz_beijing</a>&nbsp;
          链接：<a href="http://yangzhen.javaeye.com/blog/114136" style="color:red;">http://yangzhen.javaeye.com/blog/114136</a>&nbsp;
          发表时间: 2007年08月20日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          现在我要对<span style="color: red">TDDForInital</span>类进行单体测试<br />代码如下：<br />public class TDDForInital {<br /><br />	public String returnStr(String str) {<br />		<br />		if (null == str || str.length() &lt; 3) {<br />			return "";<br />		}<br /><br />		return str.replaceAll(",", "-") + <span style="color: red">new A().a();</span><br />	}<br />}<br /><br />现在我想用easymock弄掉new A().a()方法<br /><br />测试代码如下：<br />public class TestTDDForInital extends TestCase {<br /><br />	public void testReturnStr() {<br />		A control = EasyMock.createMock(A.class);<br />		control.a();<br />		EasyMock.expectLastCall().andReturn("6");<br />		EasyMock.replay(control);<br />		<br />		TDDForInital t = new TDDForInital();<br />		assertEquals("2006-03-036", t.returnStr("2006,03,03"));<br />		<br />		EasyMock.verify(control);<br />	}<br />}<br /><br /><span style="color: green">为什么测试不通过啊？现象表明new A().a()方法根本没有被mock掉。</span><br />junit.framework.ComparisonFailure: expected:&lt;2006-03-03[6]> but was:&lt;2006-03-03[]><br />	at junit.framework.Assert.assertEquals(Assert.java:81)<br />	at junit.framework.Assert.assertEquals(Assert.java:87)<br />	at test_bj.TestTDDForInital.testReturnStr(TestTDDForInital.java:21)<br />	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)<br />	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)<br />	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)<br />	at java.lang.reflect.Method.invoke(Unknown Source)<br />	at junit.framework.TestCase.runTest(TestCase.java:164)<br />	at junit.framework.TestCase.runBare(TestCase.java:130)<br />	at junit.framework.TestResult$1.protect(TestResult.java:106)<br />	at junit.framework.TestResult.runProtected(TestResult.java:124)<br />	at junit.framework.TestResult.run(TestResult.java:109)<br />	at junit.framework.TestCase.run(TestCase.java:120)<br />	at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:130)<br />	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)<br />	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)<br />	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)<br />	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)<br />	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
          <br/>
          <span style="color:red;">
            <a href="http://yangzhen.javaeye.com/blog/114136#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 20 Aug 2007 00:07:14 +0800</pubDate>
        <link>http://yangzhen.javaeye.com/blog/114136</link>
        <guid>http://yangzhen.javaeye.com/blog/114136</guid>
      </item>
      <item>
        <title>easymock扩展包里的something</title>
        <author>yz_beijing</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://yangzhen.javaeye.com">yz_beijing</a>&nbsp;
          链接：<a href="http://yangzhen.javaeye.com/blog/111006" style="color:red;">http://yangzhen.javaeye.com/blog/111006</a>&nbsp;
          发表时间: 2007年08月11日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          请问easymock扩展包里面用到的<br />net.sf.cglib.core.CollectionUtils;<br />net.sf.cglib.core.VisibilityPredicate;<br />net.sf.cglib.proxy.Callback;<br />net.sf.cglib.proxy.Enhancer;<br />net.sf.cglib.proxy.Factory;<br />net.sf.cglib.proxy.MethodInterceptor;<br />net.sf.cglib.proxy.MethodProxy;<br /><br />org.objenesis.ObjenesisException;<br />org.objenesis.ObjenesisHelper;<br /><br />都是什么包？从哪里能下载？
          <br/>
          <span style="color:red;">
            <a href="http://yangzhen.javaeye.com/blog/111006#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 11 Aug 2007 00:13:45 +0800</pubDate>
        <link>http://yangzhen.javaeye.com/blog/111006</link>
        <guid>http://yangzhen.javaeye.com/blog/111006</guid>
      </item>
      <item>
        <title>杂谈：工作一年了</title>
        <author>yz_beijing</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://yangzhen.javaeye.com">yz_beijing</a>&nbsp;
          链接：<a href="http://yangzhen.javaeye.com/blog/109520" style="color:red;">http://yangzhen.javaeye.com/blog/109520</a>&nbsp;
          发表时间: 2007年08月06日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;来到北京一年多一点了，也工作一年了，时间还真是过的快。转眼间已经没人说我是新人了，我也在工作中努力的体现自己的价值。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 进入软件行业应该是在我大学里就有的想法，但是真的做这个了自己还是有点惊讶。现在coding已经一年了，虽然学到了些知识，但是总感觉这些不是自己想要的，现在做的东西和我想的不一样。我喜欢的不是这些。所以总想学点别的东西，却不知道从何下手，以至于现在还没开始着手...</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这一年了确实发生了一些不该发生的故事，但是这就是生活，生活不能一直如你所预想的那样美好顺利，所以我接受生活，我适应生活。我生活在一个无法付出爱的世界里，生活在一个我原本不熟悉的世界了。但是我在适应，慢慢的适应，适应这个世界里怎么会没有你。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 被外派到别的公司已经3个月了，开始适应了这个公司的工作环境了，现在突然有个想法，如果我能去北京各个大的软件公司外驻那也是人生很快活的事情，我喜欢新的环境，这会让我兴奋不已。</p>
<p>&nbsp;&nbsp;&nbsp; 北京最近的雨怎么这么多，在4天的大雨中我被淋了两次，淋的彻头彻尾，淋的酣畅淋漓，大街上几乎就我一个人走在瓢泼的大雨中，虽然狼狈，但是我却笑出了声音。有人笑我是傻B，我笑傻B看不出我心中的兴奋，这样的遭遇一生中能有几次那？为什么不爽快的淋一淋那？</p>
<p>&nbsp;&nbsp;&nbsp; 最近胃口有点不好，隐隐的作痛，可能是因为吃饭不规律吧，老是饿，难道老了？</p>
<p>&nbsp;&nbsp;&nbsp; 自己文采不好，所以写什么都是杂谈，给自己一个乱写的理由....</p>
          <br/>
          <span style="color:red;">
            <a href="http://yangzhen.javaeye.com/blog/109520#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 06 Aug 2007 23:35:51 +0800</pubDate>
        <link>http://yangzhen.javaeye.com/blog/109520</link>
        <guid>http://yangzhen.javaeye.com/blog/109520</guid>
      </item>
      <item>
        <title>web开发中关于TDD的一些迷惑</title>
        <author>yz_beijing</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://yangzhen.javaeye.com">yz_beijing</a>&nbsp;
          链接：<a href="http://yangzhen.javaeye.com/blog/109228" style="color:red;">http://yangzhen.javaeye.com/blog/109228</a>&nbsp;
          发表时间: 2007年08月06日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          关于TDD的实例这里已经很多人做了说明，作为一个初学者也领会了一点东西。但也只是真对一些小的算法之类。那么我现在有点迷惑的是：<br />1：在we开发中，对于一些方法的参数，比如request,session...之类（就是我想不出怎么做出来的东西），我怎么去真实的得到它，并传给我要测试的方法。<br />2：当我做一个检索画面的时候，我需要传一个员工的id去两个表里面查出我想要的数据，并封装成一个bean泛回来。如果要想用TDD来完成他，该是个什么样的思路那？<br />请各位TDD前辈指点！！！
          <br/>
          <span style="color:red;">
            <a href="http://yangzhen.javaeye.com/blog/109228#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 06 Aug 2007 00:26:39 +0800</pubDate>
        <link>http://yangzhen.javaeye.com/blog/109228</link>
        <guid>http://yangzhen.javaeye.com/blog/109228</guid>
      </item>
      <item>
        <title>初识TDD</title>
        <author>yz_beijing</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://yangzhen.javaeye.com">yz_beijing</a>&nbsp;
          链接：<a href="http://yangzhen.javaeye.com/blog/109197" style="color:red;">http://yangzhen.javaeye.com/blog/109197</a>&nbsp;
          发表时间: 2007年08月05日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p><font size="1">&nbsp;&nbsp;&nbsp;&nbsp; <span style="FONT-SIZE: 11pt">TDD</span><span style="FONT-SIZE: 11pt">（</span><span style="FONT-SIZE: 11pt">Test Driven Development</span><span style="FONT-SIZE: 11pt">），核心思想就是以测试的方式来驱动开发，它对传统的软件开发流程做了一个有效的调整。</span><span style="FONT-SIZE: 11pt">TDD</span><span style="FONT-SIZE: 11pt">的目的主要是为了保证类是为了其所赋予的功能、职责而存在，另一方面也是为了保证避免过度设计，还有就是为了将来的重构方便，为了持续集成存在能够有意义</span><span style="FONT-SIZE: 11pt">,</span><span style="FONT-SIZE: 11pt">测试不仅带来了软件质量的提升，也同时为软件提供了详尽的文档。</span></font></p>
<font size="1"><span style="FONT-SIZE: 11pt">
<div>1 在开始真正编码之前，添加相应的能够失败的测试代码。 </div>
<div>2. 运行所有的测试，测试未通过。</div>
<div>3. 修改代码。</div>
<div>4 &nbsp;运行所有的测试，测试全部通过。</div>
<div>5 &nbsp;重构代码，消除冗余。&nbsp;&nbsp;&nbsp;</div>
</span></font>
          <br/>
          <span style="color:red;">
            <a href="http://yangzhen.javaeye.com/blog/109197#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 05 Aug 2007 22:59:39 +0800</pubDate>
        <link>http://yangzhen.javaeye.com/blog/109197</link>
        <guid>http://yangzhen.javaeye.com/blog/109197</guid>
      </item>
      <item>
        <title>详解spring事务属性</title>
        <author>yz_beijing</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://yangzhen.javaeye.com">yz_beijing</a>&nbsp;
          链接：<a href="http://yangzhen.javaeye.com/blog/109190" style="color:red;">http://yangzhen.javaeye.com/blog/109190</a>&nbsp;
          发表时间: 2007年08月05日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>Spring声明式事务让我们从复杂的事务处理中得到解脱。使得我们再也无需要去处理获得连接、关闭连接、事务提交和回滚等这些操作。再也无需要我们在与事务相关的方法中处理大量的try&hellip;catch&hellip;finally代码。 <br />
我们在使用Spring声明式事务时，有一个非常重要的概念就是事务属性。事务属性通常由事务的传播行为，事务的隔离级别，事务的超时值和事务只读标志组成。我们在进行事务划分时，需要进行事务定义，也就是配置事务的属性。 <br />
Spring在<strong>TransactionDefinition</strong>接口中定义这些属性,以供PlatfromTransactionManager使用, PlatfromTransactionManager是spring事务管理的核心接口。 <br />
</p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span>TransactionDefinition &nbsp;&nbsp;</span></span></li>
    <li class=""><span></span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">interface</span><span>&nbsp;TransactionDefinition&nbsp;{ &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">int</span><span>&nbsp;getPropagationBehavior(); &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">int</span><span>&nbsp;getIsolationLevel(); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">int</span><span>&nbsp;getTimeout(); &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">boolean</span><span>&nbsp;isReadOnly(); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
</div>
<script>render_code();</script>
<p>&nbsp;</p>
<p>getTimeout()方法，它返回事务必须在多少秒内完成。 <br />
isReadOnly(),事务是否只读，事务管理器能够根据这个返回值进行优化，确保事务是只读的。 <br />
getIsolationLevel()方法返回事务的隔离级别，事务管理器根据它来控制另外一个事务可以看到本事务内的哪些数据。</p>
<p>在TransactionDefinition接口中定义了五个不同的事务隔离级别 <br />
<strong>ISOLATION_DEFAULT </strong>这是一个PlatfromTransactionManager默认的隔离级别，使用数据库默认的事务隔离级别.另外四个与JDBC的隔离级别相对应 <br />
<strong>ISOLATION_READ_UNCOMMITTED</strong> 这是事务最低的隔离级别，它充许别外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读，不可重复读和幻像读。 <br />
例如: <br />
Mary的原工资为1000,财务人员将Mary的工资改为了8000，但未提交事务 <br />
</p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span>Connection&nbsp;con1&nbsp;=&nbsp;getConnection(); &nbsp;&nbsp;</span></span></li>
    <li class=""><span>con.setAutoCommit(</span><span class="keyword">false</span><span>); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>update&nbsp;employee&nbsp;set&nbsp;salary&nbsp;=&nbsp;</span><span class="number">8000</span><span>&nbsp;where&nbsp;empId&nbsp;=</span><span class="string">&quot;Mary&quot;</span><span>;&nbsp;&nbsp;</span></li>
</ol>
</div>
</div>
<script>render_code();</script><br />
与此同时，Mary正在读取自己的工资 <br />
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span>Connection&nbsp;con2&nbsp;=&nbsp;getConnection(); &nbsp;&nbsp;</span></span></li>
    <li class=""><span>select&nbsp;&nbsp;salary&nbsp;from&nbsp;employee&nbsp;where&nbsp;empId&nbsp;=</span><span class="string">&quot;Mary&quot;</span><span>; &nbsp;&nbsp;</span></li>
    <li class="alt"><span>con2.commit();&nbsp;&nbsp;</span></li>
</ol>
</div>
</div>
<script>render_code();</script>
<p>&nbsp;</p>
<p>Mary发现自己的工资变为了8000，欢天喜地！ <br />
而财务发现操作有误，而回滚了事务,Mary的工资又变为了1000 <br />
</p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span class="comment">//con1 </span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;con1.rollback();&nbsp;&nbsp;</span></li>
</ol>
</div>
</div>
<script>render_code();</script><br />
像这样,Mary记取的工资数8000是一个脏数据。
<p>&nbsp;</p>
<p><strong>ISOLATION_READ_COMMITTED </strong>保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现，但是可能会出现不可重复读和幻像读。</p>
<p><strong>ISOLATION_REPEATABLE_READ </strong>这种事务隔离级别可以防止脏读，不可重复读。但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外，还保证了避免下面的情况产生(不可重复读)。</p>
<p>在事务1中，Mary 读取了自己的工资为1000,操作并没有完成 <br />
</p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span>con1&nbsp;=&nbsp;getConnection(); &nbsp;&nbsp;</span></span></li>
    <li class=""><span>select&nbsp;salary&nbsp;from&nbsp;employee&nbsp;empId&nbsp;=</span><span class="string">&quot;Mary&quot;</span><span>;&nbsp;&nbsp;</span></li>
</ol>
</div>
</div>
<script>render_code();</script>
<p>&nbsp;</p>
<p>在事务2中，这时财务人员修改了Mary的工资为2000,并提交了事务. <br />
</p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span>con2&nbsp;=&nbsp;getConnection(); &nbsp;&nbsp;</span></span></li>
    <li class=""><span>update&nbsp;employee&nbsp;set&nbsp;salary&nbsp;=&nbsp;</span><span class="number">2000</span><span>; &nbsp;&nbsp;</span></li>
    <li class="alt"><span>con2.commit();&nbsp;&nbsp;</span></li>
</ol>
</div>
</div>
<script>render_code();</script>
<p>&nbsp;</p>
<p>在事务1中，Mary 再次读取自己的工资时，工资变为了2000 <br />
</p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span class="comment">//con1 </span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>select&nbsp;salary&nbsp;from&nbsp;employee&nbsp;empId&nbsp;=</span><span class="string">&quot;Mary&quot;</span><span>;&nbsp;&nbsp;</span></li>
</ol>
</div>
</div>
<script>render_code();</script>
<p>&nbsp;</p>
<p>在一个事务中前后两次读取的结果并不致，导致了不可重复读。 <br />
使用ISOLATION_REPEATABLE_READ可以避免这种情况发生。</p>
<p><strong>ISOLATION_SERIALIZABLE </strong>这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读，不可重复读外，还避免了幻像读。</p>
<p>目前工资为1000的员工有10人。 <br />
事务1,读取所有工资为1000的员工。 <br />
</p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span>con1&nbsp;=&nbsp;getConnection(); &nbsp;&nbsp;</span></span></li>
    <li class=""><span>Select&nbsp;*&nbsp;from&nbsp;employee&nbsp;where&nbsp;salary&nbsp;=</span><span class="number">1000</span><span>;&nbsp;&nbsp;</span></li>
</ol>
</div>
</div>
<script>render_code();</script>共读取10条记录
<p>&nbsp;</p>
<p>这时另一个事务向employee表插入了一条员工记录，工资也为1000 <br />
</p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span>con2&nbsp;=&nbsp;getConnection(); &nbsp;&nbsp;</span></span></li>
    <li class=""><span>Insert&nbsp;into&nbsp;employee(empId,salary)&nbsp;values(</span><span class="string">&quot;Lili&quot;</span><span>,</span><span class="number">1000</span><span>); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>con2.commit();&nbsp;&nbsp;</span></li>
</ol>
</div>
</div>
<script>render_code();</script>
<p>&nbsp;</p>
<p>事务1再次读取所有工资为1000的员工 <br />
</p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span class="comment">//con1 </span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>select&nbsp;*&nbsp;from&nbsp;employee&nbsp;where&nbsp;salary&nbsp;=</span><span class="number">1000</span><span>;&nbsp;&nbsp;</span></li>
</ol>
</div>
</div>
<script>render_code();</script>
<p>&nbsp;</p>
<p>共读取到了11条记录，这就产生了幻像读。 <br />
ISOLATION_SERIALIZABLE能避免这样的情况发生。但是这样也耗费了最大的资源。</p>
<p><strong>getPropagationBehavior()</strong>返回事务的传播行为，由是否有一个活动的事务来决定一个事务调用。</p>
<p><strong>在TransactionDefinition接口中定义了七个事务传播行为</strong>。</p>
<p><strong>PROPAGATION_REQUIRED </strong>如果存在一个事务，则支持当前事务。如果没有事务则开启一个新的事务。</p>
<p>&nbsp;</p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span class="comment">//事务属性&nbsp;PROPAGATION_REQUIRED </span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>methodA{ &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&hellip;&hellip; &nbsp;&nbsp;</span></li>
    <li class=""><span>methodB(); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&hellip;&hellip; &nbsp;&nbsp;</span></li>
    <li class=""><span>} &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span></span><span class="comment">//事务属性&nbsp;PROPAGATION_REQUIRED </span><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span>methodB{ &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&hellip;&hellip; &nbsp;&nbsp;</span></li>
    <li class="alt"><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
</div>
<script>render_code();</script><br />
使用spring声明式事务，spring使用AOP来支持声明式事务，会根据事务属性，自动在方法调用之前决定是否开启一个事务，并在方法执行之后决定事务提交或回滚事务。
<p>&nbsp;</p>
<p>单独调用methodB方法 <br />
</p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<ol class="dp-j">
    <li class="alt"><span><span>main{ &nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;metodB(); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
</div>
<script>render_code();</script><br />
相当于 <br />
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span>Main{ &nbsp;&nbsp;</span></span></li>
    <li class=""><span>Connection&nbsp;con=</span><span class="keyword">null</span><span>; &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;rry{ &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;con&nbsp;=&nbsp;getConnection(); &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;con.setAutoCommit(</span><span class="keyword">false</span><span>); &nbsp;&nbsp;</span></li>
    <li class="alt"><span></span><span class="comment">//方法调用 </span><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>methodB(); &nbsp;&nbsp;</span></li>
    <li class="alt"><span></span><span class="comment">//提交事务 </span><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>con.commit(); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>} &nbsp;&nbsp;</span></li>
    <li class=""><span>Catch(RuntimeException&nbsp;ex){ &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span><span class="comment">//回滚事务 </span><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;con.rollback();&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li class="alt"><span>} &nbsp;&nbsp;</span></li>
    <li class=""><span></span><span class="keyword">finally</span><span>{ &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span><span class="comment">//释放资源 </span><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;closeCon(); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>} &nbsp;&nbsp;</span></li>
    <li class=""><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
</div>
<script>render_code();</script><br />
Spring保证在methodB方法中所有的调用都获得到一个相同的连接。在调用methodB时，没有一个存在的事务，所以获得一个新的连接，开启了一个新的事务。
<p>&nbsp;</p>
<p>单独调用MethodA时，在MethodA内又会调用MethodB.</p>
<p>执行效果相当于 <br />
</p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span>main{ &nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;Connection&nbsp;con&nbsp;=&nbsp;</span><span class="keyword">null</span><span>; &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;</span><span class="keyword">try</span><span>{ &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;con&nbsp;=&nbsp;getConnection(); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;methodA(); &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;con.commit(); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>} &nbsp;&nbsp;</span></li>
    <li class=""><span>cathc(RuntimeException&nbsp;ex){ &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;con.rollback(); &nbsp;&nbsp;</span></li>
    <li class=""><span>} &nbsp;&nbsp;</span></li>
    <li class="alt"><span></span><span class="keyword">finally</span><span>{ &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;closeCon(); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>}&nbsp; &nbsp;&nbsp;</span></li>
    <li class=""><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
</div>
<script>render_code();</script><br />
调用MethodA时，环境中没有事务，所以开启一个新的事务. <br />
当在MethodA中调用MethodB时，环境中已经有了一个事务，所以methodB就加入当前事务。
<p>&nbsp;</p>
<p><strong>PROPAGATION_SUPPORTS </strong>如果存在一个事务，支持当前事务。如果没有事务，则非事务的执行。但是对于事务同步的事务管理器，PROPAGATION_SUPPORTS与不使用事务有少许不同。</p>
<p>&nbsp;</p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span class="comment">//事务属性&nbsp;PROPAGATION_REQUIRED&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>methodA(){ &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;methodB(); &nbsp;&nbsp;</span></li>
    <li class=""><span>} &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span></span><span class="comment">//事务属性&nbsp;PROPAGATION_SUPPORTS&nbsp; </span><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span>methodB(){ &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&hellip;&hellip; &nbsp;&nbsp;</span></li>
    <li class="alt"><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
</div>
<script>render_code();</script><br />
单纯的调用methodB时，methodB方法是非事务的执行的。 <br />
当调用methdA时,methodB则加入了methodA的事务中,事务地执行。
<p>&nbsp;</p>
<p>PROPAGATION_MANDATORY 如果已经存在一个事务，支持当前事务。如果没有一个活动的事务，则抛出异常。</p>
<p>&nbsp;</p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span class="comment">//事务属性&nbsp;PROPAGATION_REQUIRED&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>methodA(){ &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;methodB(); &nbsp;&nbsp;</span></li>
    <li class=""><span>} &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span></span><span class="comment">//事务属性&nbsp;PROPAGATION_MANDATORY&nbsp; </span><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span>methodB(){ &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&hellip;&hellip; &nbsp;&nbsp;</span></li>
    <li class="alt"><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
</div>
<script>render_code();</script><br />
当单独调用methodB时，因为当前没有一个活动的事务，则会抛出异常 <br />
throw new IllegalTransactionStateException(&quot;Transaction propagation 'mandatory' but no existing transaction found&quot;);
<p>&nbsp;</p>
<p>当调用methodA时，methodB则加入到methodA的事务中，事务地执行。</p>
<p><strong>PROPAGATION_REQUIRES_NEW </strong>总是开启一个新的事务。如果一个事务已经存在，则将这个存在的事务挂起。</p>
<p>&nbsp;</p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span class="comment">//事务属性&nbsp;PROPAGATION_REQUIRED&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>methodA(){ &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;doSomeThingA(); &nbsp;&nbsp;</span></li>
    <li class=""><span>methodB(); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>doSomeThingB(); &nbsp;&nbsp;</span></li>
    <li class=""><span>} &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span></span><span class="comment">//事务属性&nbsp;PROPAGATION_REQUIRES_NEW&nbsp; </span><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span>methodB(){ &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&hellip;&hellip; &nbsp;&nbsp;</span></li>
    <li class="alt"><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
</div>
<script>render_code();</script><br />
当单独调用methodB时，相当于把methodb声明为REQUIRED。开启一个新的事务，事务地执行。
<p>&nbsp;</p>
<p>当调用methodA时 <br />
</p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<ol class="dp-j">
    <li class="alt"><span><span>main(){ &nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;methodA(); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
</div>
<script>render_code();</script>情况有些大不一样.相当于下面的效果。 <br />
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span>main(){ &nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;TransactionManager&nbsp;tm&nbsp;=&nbsp;</span><span class="keyword">null</span><span>; &nbsp;&nbsp;</span></li>
    <li class="alt"><span></span><span class="keyword">try</span><span>{ &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;</span><span class="comment">//获得一个JTA事务管理器 </span><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;tm&nbsp;=&nbsp;getTransactionManager(); &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;tm.begin();</span><span class="comment">//开启一个新的事务 </span><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;Transaction&nbsp;ts1&nbsp;=&nbsp;tm.getTransaction(); &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;doSomeThing(); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;tm.suspend();</span><span class="comment">//挂起当前事务 </span><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;</span><span class="keyword">try</span><span>{ &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tm.begin();</span><span class="comment">//重新开启第二个事务 </span><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Transaction&nbsp;ts2&nbsp;=&nbsp;tm.getTransaction(); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;methodB(); &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ts2.commit();</span><span class="comment">//提交第二个事务 </span><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;Catch(RunTimeException&nbsp;ex){ &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ts2.rollback();</span><span class="comment">//回滚第二个事务 </span><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;</span><span class="keyword">finally</span><span>{ &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//释放资源 </span><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;</span><span class="comment">//methodB执行完后，复恢第一个事务 </span><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;tm.resume(ts1); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>doSomeThingB(); &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;ts1.commit();</span><span class="comment">//提交第一个事务 </span><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span>} &nbsp;&nbsp;</span></li>
    <li class=""><span></span><span class="keyword">catch</span><span>(RunTimeException&nbsp;ex){ &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;ts1.rollback();</span><span class="comment">//回滚第一个事务 </span><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>} &nbsp;&nbsp;</span></li>
    <li class="alt"><span></span><span class="keyword">finally</span><span>{ &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;</span><span class="comment">//释放资源 </span><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span>} &nbsp;&nbsp;</span></li>
    <li class=""><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
</div>
<script>render_code();</script><br />
在这里，我把ts1称为外层事务，ts2称为内层事务。从上面的代码可以看出，ts2与ts1是两个独立的事务，互不相干。Ts2是否成功并不依赖于ts1。如果methodA方法在调用methodB方法后的doSomeThingB方法失败了，而methodB方法所做的结果依然被提交。而除了methodB之外的其它代码导致的结果却被回滚了。 <br />
使用PROPAGATION_REQUIRES_NEW,需要使用JtaTransactionManager作为事务管理器。
<p>&nbsp;</p>
<p><strong>PROPAGATION_NOT_SUPPORTED</strong> 总是非事务地执行，并挂起任何存在的事务。</p>
<p>&nbsp;</p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span class="comment">//事务属性&nbsp;PROPAGATION_REQUIRED&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>methodA(){ &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;doSomeThingA(); &nbsp;&nbsp;</span></li>
    <li class=""><span>methodB(); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>doSomeThingB(); &nbsp;&nbsp;</span></li>
    <li class=""><span>} &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span></span><span class="comment">//事务属性&nbsp;PROPAGATION_NOT_SUPPORTED&nbsp; </span><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span>methodB(){ &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&hellip;&hellip; &nbsp;&nbsp;</span></li>
    <li class="alt"><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
</div>
<script>render_code();</script><br />
当单独调用methodB时，不启用任何事务机制，非事务地执行。 <br />
当调用methodA时，相当于下面的效果
<p>&nbsp;</p>
<p>&nbsp;</p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span>main(){ &nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;TransactionManager&nbsp;tm&nbsp;=&nbsp;</span><span class="keyword">null</span><span>; &nbsp;&nbsp;</span></li>
    <li class="alt"><span></span><span class="keyword">try</span><span>{ &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;</span><span class="comment">//获得一个JTA事务管理器 </span><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;tm&nbsp;=&nbsp;getTransactionManager(); &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;tm.begin();</span><span class="comment">//开启一个新的事务 </span><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;Transaction&nbsp;ts1&nbsp;=&nbsp;tm.getTransaction(); &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;doSomeThing(); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;tm.suspend();</span><span class="comment">//挂起当前事务 </span><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;methodB(); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;</span><span class="comment">//methodB执行完后，复恢第一个事务 </span><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;tm.resume(ts1); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>doSomeThingB(); &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;ts1.commit();</span><span class="comment">//提交第一个事务 </span><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span>} &nbsp;&nbsp;</span></li>
    <li class=""><span></span><span class="keyword">catch</span><span>(RunTimeException&nbsp;ex){ &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;ts1.rollback();</span><span class="comment">//回滚第一个事务 </span><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>} &nbsp;&nbsp;</span></li>
    <li class="alt"><span></span><span class="keyword">finally</span><span>{ &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;</span><span class="comment">//释放资源 </span><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span>} &nbsp;&nbsp;</span></li>
    <li class=""><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
</div>
<script>render_code();</script>使用PROPAGATION_NOT_SUPPORTED,也需要使用JtaTransactionManager作为事务管理器。
<p>&nbsp;</p>
<p><strong>PROPAGATION_NEVER</strong> 总是非事务地执行，如果存在一个活动事务，则抛出异常</p>
<p>&nbsp;</p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span class="comment">//事务属性&nbsp;PROPAGATION_REQUIRED&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>methodA(){ &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;doSomeThingA(); &nbsp;&nbsp;</span></li>
    <li class=""><span>methodB(); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>doSomeThingB(); &nbsp;&nbsp;</span></li>
    <li class=""><span>} &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span></span><span class="comment">//事务属性&nbsp;PROPAGATION_NEVER&nbsp; </span><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span>methodB(){ &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&hellip;&hellip; &nbsp;&nbsp;</span></li>
    <li class="alt"><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
</div>
<script>render_code();</script>单独调用methodB，则非事务的执行。 <br />
调用methodA则会抛出异常 <br />
throw new IllegalTransactionStateException( <br />
&quot;Transaction propagation 'never' but existing transaction found&quot;);
<p>&nbsp;</p>
<p><strong>PROPAGATION_NESTED</strong>如果一个活动的事务存在，则运行在一个嵌套的事务中. 如果没有活动事务, 则按TransactionDefinition.PROPAGATION_REQUIRED 属性执行</p>
<p>这是一个嵌套事务,使用JDBC 3.0驱动时,仅仅支持DataSourceTransactionManager作为事务管理器。需要JDBC 驱动的java.sql.Savepoint类。有一些JTA的事务管理器实现可能也提供了同样的功能。</p>
<p>使用PROPAGATION_NESTED，还需要把PlatformTransactionManager的nestedTransactionAllowed属性设为true; <br />
而nestedTransactionAllowed属性值默认为false; <br />
</p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span class="comment">//事务属性&nbsp;PROPAGATION_REQUIRED&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>methodA(){ &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;doSomeThingA(); &nbsp;&nbsp;</span></li>
    <li class=""><span>methodB(); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>doSomeThingB(); &nbsp;&nbsp;</span></li>
    <li class=""><span>} &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span></span><span class="comment">//事务属性&nbsp;PROPAGATION_NESTED </span><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span>methodB(){ &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&hellip;&hellip; &nbsp;&nbsp;</span></li>
    <li class="alt"><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
</div>
<script>render_code();</script><br />
如果单独调用methodB方法，则按REQUIRED属性执行。
<p>&nbsp;</p>
<p>如果调用methodA方法，相当于下面的效果 <br />
</p>
<div class="code_title">代码</div>
<div class="code_div">
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span>main(){ &nbsp;&nbsp;</span></span></li>
    <li class=""><span>Connection&nbsp;con&nbsp;=&nbsp;</span><span class="keyword">null</span><span>; &nbsp;&nbsp;</span></li>
    <li class="alt"><span>Savepoint&nbsp;savepoint&nbsp;=&nbsp;</span><span class="keyword">null</span><span>; &nbsp;&nbsp;</span></li>
    <li class=""><span></span><span class="keyword">try</span><span>{ &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;con&nbsp;=&nbsp;getConnection(); &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;con.setAutoCommit(</span><span class="keyword">false</span><span>); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;doSomeThingA(); &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;savepoint&nbsp;=&nbsp;con2.setSavepoint(); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span><span class="keyword">try</span><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;methodB(); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;}</span><span class="keyword">catch</span><span>(RuntimeException&nbsp;ex){ &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;con.rollback(savepoint); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;</span><span class="keyword">finally</span><span>{ &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//释放资源 </span><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;doSomeThingB(); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;con.commit(); &nbsp;&nbsp;</span></li>
    <li class=""><span>} &nbsp;&nbsp;</span></li>
    <li class="alt"><span></span><span class="keyword">catch</span><span>(RuntimeException&nbsp;ex){ &nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;con.rollback(); &nbsp;&nbsp;</span></li>
    <li class="alt"><span>} &nbsp;&nbsp;</span></li>
    <li class=""><span></span><span class="keyword">finally</span><span>{ &nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span><span class="comment">//释放资源 </span><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>} &nbsp;&nbsp;</span></li>
    <li class="alt"><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
</div>
<script>render_code();</script>当methodB方法调用之前，调用setSavepoint方法，保存当前的状态到savepoint。如果methodB方法调用失败，则恢复到之前保存的状态。但是需要注意的是，这时的事务并没有进行提交，如果后续的代码(doSomeThingB()方法)调用失败，则回滚包括methodB方法的所有操作。
<p>&nbsp;</p>
<p><strong>嵌套事务一个非常重要的概念就是内层事务依赖于外层事务。外层事务失败时，会回滚内层事务所做的动作。而内层事务操作失败并不会引起外层事务的回滚</strong>。</p>
<p><strong>PROPAGATION_NESTED 与PROPAGATION_REQUIRES_NEW的区别</strong>:它们非常类似,都像一个嵌套事务，如果不存在一个活动的事务，都会开启一个新的事务。使用PROPAGATION_REQUIRES_NEW时，内层事务与外层事务就像两个独立的事务一样，一旦内层事务进行了提交后，外层事务不能对其进行回滚。两个事务互不影响。两个事务不是一个真正的嵌套事务。同时它需要JTA事务管理器的支持。 <br />
使用PROPAGATION_NESTED时，外层事务的回滚可以引起内层事务的回滚。而内层事务的异常并不会导致外层事务的回滚，它是一个真正的嵌套事务。DataSourceTransactionManager使用savepoint支持PROPAGATION_NESTED时，需要JDBC 3.0以上驱动及1.4以上的JDK版本支持。其它的JTA TrasactionManager实现可能有不同的支持方式。</p>
<p>PROPAGATION_REQUIRED应该是我们首先的事务传播行为。它能够满足我们大多数的事务需求。</p>
          <br/>
          <span style="color:red;">
            <a href="http://yangzhen.javaeye.com/blog/109190#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 05 Aug 2007 22:11:40 +0800</pubDate>
        <link>http://yangzhen.javaeye.com/blog/109190</link>
        <guid>http://yangzhen.javaeye.com/blog/109190</guid>
      </item>
      <item>
        <title>关于YUI的问题</title>
        <author>yz_beijing</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://yangzhen.javaeye.com">yz_beijing</a>&nbsp;
          链接：<a href="http://yangzhen.javaeye.com/blog/65789" style="color:red;">http://yangzhen.javaeye.com/blog/65789</a>&nbsp;
          发表时间: 2007年03月27日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          现在想学学YUI，可是在做例子的过程中遇到了点问题，就是在引YUI的类的时候不知道该去哪个包里找。<br />比如想用到一些控件的时候，总找不到在哪个包里。还有yui-ext.js和utilities_2.1.0.js里包括了YUI里的所有类吗？是不是引了这两个之后就不用在引别的了？<br />&lt;script type="text/javascript" src="../../build/utilities_2.1.0.js">&lt;/script><br />&lt;script type="text/javascript" src="../../build/yui-ext.js">&lt;/script><br /><br />有知道的朋友帮解答一下，谢谢了<img src="/images/smiles/icon_wink.gif"/>
          <br/>
          <span style="color:red;">
            <a href="http://yangzhen.javaeye.com/blog/65789#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 27 Mar 2007 11:17:21 +0800</pubDate>
        <link>http://yangzhen.javaeye.com/blog/65789</link>
        <guid>http://yangzhen.javaeye.com/blog/65789</guid>
      </item>
  </channel>
</rss>