﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-Roy's Blog-随笔分类-SSH</title><link>http://www.blogjava.net/RoyPayne/category/50539.html</link><description>－敲击思想的键盘，滑动灵感的鼠标。</description><language>zh-cn</language><lastBuildDate>Mon, 30 Jan 2012 17:30:50 GMT</lastBuildDate><pubDate>Mon, 30 Jan 2012 17:30:50 GMT</pubDate><ttl>60</ttl><item><title>Hibernate n+1问题</title><link>http://www.blogjava.net/RoyPayne/archive/2012/01/30/369017.html</link><dc:creator>RoyPayne</dc:creator><author>RoyPayne</author><pubDate>Mon, 30 Jan 2012 06:20:00 GMT</pubDate><guid>http://www.blogjava.net/RoyPayne/archive/2012/01/30/369017.html</guid><wfw:comment>http://www.blogjava.net/RoyPayne/comments/369017.html</wfw:comment><comments>http://www.blogjava.net/RoyPayne/archive/2012/01/30/369017.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/RoyPayne/comments/commentRss/369017.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/RoyPayne/services/trackbacks/369017.html</trackback:ping><description><![CDATA[<div><div id="cnblogs_post_body"><p align="left"><span size="3" style="font-size: small;">在Session的缓存中存放的是相互关联的对象图。默认情况下，当Hibernate从数据库中加载Customer对象时，会同时加载所有关联的 Order对象。以Customer和Order类为例，假定ORDERS表的CUSTOMER_ID外键允许为null<br /><br />以下Session的find()方法用于到数据库中检索所有的Customer对象：&nbsp;<br /><br />List customerLists=session.find("from Customer as c");&nbsp;<br /><br />运行以上find()方法时，Hibernate将先查询CUSTOMERS表中所有的记录，然后根据每条记录的ID，到ORDERS表中查询有参照关系的记录，Hibernate将依次执行以下select语句：&nbsp;<br /><br />select * from CUSTOMERS;&nbsp;<br />select * from ORDERS where CUSTOMER_ID=1;&nbsp;<br />select * from ORDERS where CUSTOMER_ID=2;&nbsp;<br />select * from ORDERS where CUSTOMER_ID=3;&nbsp;<br />select * from ORDERS where CUSTOMER_ID=4;&nbsp;<br /><br />通过以上5条select语句，Hibernate最后加载了4个Customer对象和5个Order对象，在内存中形成了一幅关联的对象图.<br /><br /><br />Hibernate在检索与Customer关联的Order对象时，使用了默认的立即检索策略。这种检索策略存在两大不足：&nbsp;<br /><br />（1）   select语句的数目太多，需要频繁的访问数据库，会影响检索性能。如果需要查询n个Customer对象，那么必须执行n+1次select查询语 句。这就是经典的n+1次select查询问题。这种检索策略没有利用SQL的连接查询功能，例如以上5条select语句完全可以通过以下1条 select语句来完成：&nbsp;<br /><br />select * from CUSTOMERS left outer join ORDERS&nbsp;<br />on CUSTOMERS.ID=ORDERS.CUSTOMER_ID&nbsp;<br /><br />以上select语句使用了SQL的左外连接查询功能，能够在一条select语句中查询出CUSTOMERS表的所有记录，以及匹配的ORDERS表的记录。&nbsp;<br /><br />（2）在应用逻辑只需要访问Customer对象，而不需要访问Order对象的场合，加载Order对象完全是多余的操作，这些多余的Order对象白白浪费了许多内存空间。&nbsp;<br />为了解决以上问题，<span color="#ff0000" style="color: #ff0000;">Hibernate提供了其他两种检索策略：延迟检索策略和迫切左外连接检索策略。延迟检索策略能避免多余加载应用程序不需要访问的关联对象，迫切左外连接检索策略则充分利用了SQL的外连接查询功能，能够减少select语句的数目。</span></span></p> <p align="left"><span size="3" style="font-size: small;"><br />对数据库访问还是必须考虑性能问题的， 在设定了1 对多这种关系之后， 查询就会出现传说中的n +1 问题。&nbsp;<br />1 ）1 对多，在1 方，查找得到了n 个对象， 那么又需要将n 个对象关联的集合取出，于是本来的一条sql查询变成了n +1 条&nbsp;<br />2）多对1 ，在多方，查询得到了m个对象，那么也会将m个对象对应的1 方的对象取出， 也变成了m+1</span></p> <p align="left"><span size="3" style="font-size: small;">怎么解决n +1 问题？&nbsp;<br />1 ）lazy=true， hibernate3开始已经默认是lazy=true了；lazy=true时不会立刻查询关联对象，只有当需要关联对象（访问其属性，非id字段）时才会发生查询动作。&nbsp;<br /></span></p> <p align="left"><span size="3" style="font-size: small;">2）二级缓存， 在对象更新，删除，添加相对于查询要少得多时， 二级缓存的应用将不怕n +1 问题，因为即使第一次查询很慢，之后直接缓存命中也是很快的。&nbsp;<br />不同解决方法，不同的思路，第二条却刚好又利用了n +1 。</span></p> <p align="left"><span size="3" style="font-size: small;">3) 当然你也可以设定fetch=join(annotation : @ManyToOne()&nbsp;@Fetch(FetchMode.JOIN))</span></p></div></div><img src ="http://www.blogjava.net/RoyPayne/aggbug/369017.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/RoyPayne/" target="_blank">RoyPayne</a> 2012-01-30 14:20 <a href="http://www.blogjava.net/RoyPayne/archive/2012/01/30/369017.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>spring security 权限控制</title><link>http://www.blogjava.net/RoyPayne/archive/2012/01/20/368785.html</link><dc:creator>RoyPayne</dc:creator><author>RoyPayne</author><pubDate>Fri, 20 Jan 2012 02:41:00 GMT</pubDate><guid>http://www.blogjava.net/RoyPayne/archive/2012/01/20/368785.html</guid><wfw:comment>http://www.blogjava.net/RoyPayne/comments/368785.html</wfw:comment><comments>http://www.blogjava.net/RoyPayne/archive/2012/01/20/368785.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/RoyPayne/comments/commentRss/368785.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/RoyPayne/services/trackbacks/368785.html</trackback:ping><description><![CDATA[<strong style="font-size: 14px; font-weight: bold; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; text-align: left; background-color: #ffffff; ">1. 在web.xml文件中加入Filter声明</strong>&nbsp;<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008000; ">&lt;!--</span><span style="color: #008000; ">&nbsp;Spring&nbsp;security&nbsp;Filter&nbsp;</span><span style="color: #008000; ">--&gt;</span><br /><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">filter</span><span style="color: #0000FF; ">&gt;</span><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">filter-name</span><span style="color: #0000FF; ">&gt;</span>springSecurityFilterChain<span style="color: #0000FF; ">&lt;/</span><span style="color: #800000; ">filter-name</span><span style="color: #0000FF; ">&gt;</span><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">filter-class</span><span style="color: #0000FF; ">&gt;</span>org.springframework.web.filter.DelegatingFilterProxy<span style="color: #0000FF; ">&lt;/</span><span style="color: #800000; ">filter-class</span><span style="color: #0000FF; ">&gt;</span><br /><span style="color: #0000FF; ">&lt;/</span><span style="color: #800000; ">filter</span><span style="color: #0000FF; ">&gt;</span><br /><span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">filter-mapping</span><span style="color: #0000FF; ">&gt;</span><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">filter-name</span><span style="color: #0000FF; ">&gt;</span>springSecurityFilterChain<span style="color: #0000FF; ">&lt;/</span><span style="color: #800000; ">filter-name</span><span style="color: #0000FF; ">&gt;</span><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">&lt;</span><span style="color: #800000; ">url-pattern</span><span style="color: #0000FF; ">&gt;</span>/*<span style="color: #0000FF; ">&lt;/</span><span style="color: #800000; ">url-pattern</span><span style="color: #0000FF; ">&gt;</span><br /><span style="color: #0000FF; ">&lt;/</span><span style="color: #800000; ">filter-mapping</span><span style="color: #0000FF; ">&gt;</span></div><br /><span class="Apple-style-span" style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 25px; background-color: #ffffff; ">这个Filter会拦截所有的URL请求，并且对这些URL请求进行Spring Security的验证。&nbsp;</span><br /><div><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; line-height: 25px; text-align: left; background-color: #ffffff; " /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; line-height: 25px; text-align: left; background-color: #ffffff; ">注意，springSecurityFilterChain这个名称是由命名空间默认创建的用于处理web安全的一个内部的bean的id。所以你在你的Spring配置文件中，不应该再使用这个id作为你的bean。&nbsp;</span><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; line-height: 25px; text-align: left; background-color: #ffffff; " /><br style="font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; line-height: 25px; text-align: left; background-color: #ffffff; " /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; line-height: 25px; text-align: left; background-color: #ffffff; ">与Acegi的配置不同，Acegi需要自行声明一个Spring的bean来作为Filter的实现，而使用Spring Security后，无需再额外定义bean，而是使用&lt;http&gt;元素进行配置。&nbsp;</span></div><br /><strong style="font-weight: bold; font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; line-height: 25px; text-align: left; "><span style="color: blue; ">通过扩展Spring Security的默认实现来进行用户和权限的管理</span></strong>&nbsp;<br /><br /><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; line-height: 25px; ">事实上，Spring Security提供了2个认证的接口，分别用于模拟用户和权限，以及读取用户和权限的操作方法。这两个接口分别是：UserDetails和UserDetailsService。&nbsp;<br /></span><br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">interface</span>&nbsp;UserDetails&nbsp;<span style="color: #0000FF; ">extends</span>&nbsp;Serializable&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;GrantedAuthority[]&nbsp;getAuthorities();<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;getPassword();<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;getUsername();<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">boolean</span>&nbsp;isAccountNonExpired();<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">boolean</span>&nbsp;isAccountNonLocked();<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">boolean</span>&nbsp;isCredentialsNonExpired();<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">boolean</span>&nbsp;isEnabled();<br />}</div><br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">interface</span>&nbsp;UserDetailsService&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;UserDetails&nbsp;loadUserByUsername(String&nbsp;username)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">throws</span>&nbsp;UsernameNotFoundException,&nbsp;DataAccessException;<br />}</div><br /><div><span style="font-family: Helvetica, Tahoma, Arial, sans-serif; font-size: 14px; line-height: 25px; background-color: #ffffff; ">非常清楚，一个接口用于模拟用户，另外一个用于模拟读取用户的过程。所以我们可以通过实现这两个接口，来完成使用数据库对用户和权限进行管理的需求。在这里，我将给出一个使用Hibernate来定义用户和权限之间关系的示例。&nbsp;</span></div><img src ="http://www.blogjava.net/RoyPayne/aggbug/368785.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/RoyPayne/" target="_blank">RoyPayne</a> 2012-01-20 10:41 <a href="http://www.blogjava.net/RoyPayne/archive/2012/01/20/368785.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring中Quartz的配置</title><link>http://www.blogjava.net/RoyPayne/archive/2012/01/19/368757.html</link><dc:creator>RoyPayne</dc:creator><author>RoyPayne</author><pubDate>Thu, 19 Jan 2012 06:53:00 GMT</pubDate><guid>http://www.blogjava.net/RoyPayne/archive/2012/01/19/368757.html</guid><wfw:comment>http://www.blogjava.net/RoyPayne/comments/368757.html</wfw:comment><comments>http://www.blogjava.net/RoyPayne/archive/2012/01/19/368757.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/RoyPayne/comments/commentRss/368757.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/RoyPayne/services/trackbacks/368757.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Quartz是一个强大的企业级任务调度框架，Spring中继承并简化了Quartz，下面就看看在Spring中怎样配置Quartz：&nbsp;&nbsp;<a href='http://www.blogjava.net/RoyPayne/archive/2012/01/19/368757.html'>阅读全文</a><img src ="http://www.blogjava.net/RoyPayne/aggbug/368757.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/RoyPayne/" target="_blank">RoyPayne</a> 2012-01-19 14:53 <a href="http://www.blogjava.net/RoyPayne/archive/2012/01/19/368757.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts2-拦截器-权限控制</title><link>http://www.blogjava.net/RoyPayne/archive/2012/01/17/368664.html</link><dc:creator>RoyPayne</dc:creator><author>RoyPayne</author><pubDate>Tue, 17 Jan 2012 08:35:00 GMT</pubDate><guid>http://www.blogjava.net/RoyPayne/archive/2012/01/17/368664.html</guid><wfw:comment>http://www.blogjava.net/RoyPayne/comments/368664.html</wfw:comment><comments>http://www.blogjava.net/RoyPayne/archive/2012/01/17/368664.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/RoyPayne/comments/commentRss/368664.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/RoyPayne/services/trackbacks/368664.html</trackback:ping><description><![CDATA[1.自定义拦截器继承AbstractInterceptor，重写public String intercept(ActionInvocation invocation)方法。<br />intercept方法有ActionInvocation对象，可以获取当前的Action请求。<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">public</span>&nbsp;<span style="color: #0000FF; ">class</span>&nbsp;AuthorityInterceptor&nbsp;<span style="color: #0000FF; ">extends</span>&nbsp;AbstractInterceptor&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">private</span>&nbsp;<span style="color: #0000FF; ">static</span>&nbsp;<span style="color: #0000FF; ">final</span>&nbsp;<span style="color: #0000FF; ">long</span>&nbsp;serialVersionUID&nbsp;=&nbsp;1L;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">private</span>&nbsp;Logger&nbsp;LOG&nbsp;=&nbsp;Logger.getLogger(AuthorityInterceptor.<span style="color: #0000FF; ">class</span>.getName());&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">private</span>&nbsp;AuthorityUtil&nbsp;authorityUtil;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>&nbsp;String&nbsp;intercept(ActionInvocation&nbsp;invocation)&nbsp;<span style="color: #0000FF; ">throws</span>&nbsp;Exception&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(authorityUtil&nbsp;==&nbsp;<span style="color: #0000FF; ">null</span>)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;authorityUtil&nbsp;=&nbsp;<span style="color: #0000FF; ">new</span>&nbsp;AuthorityUtil();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">获取当前用户所有的权限</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List&lt;OperatorPurviewDO&gt;&nbsp;operatorPurviews&nbsp;=&nbsp;getCurrentOperatorPurviews();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">获取当前操作的url</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;currentUrl&nbsp;=&nbsp;getCurrentUrl();&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">如果是超级管理员或有当前url的权限，那么直接返回。</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(OperatorUtil.getIsSuperAdmin()&nbsp;||(OperatorUtil.getLoginName()!=<span style="color: #0000FF; ">null</span>&amp;&amp;authorityUtil.checkUrl(operatorPurviews,&nbsp;currentUrl))){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;invocation.invoke();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(!OperatorUtil.getIsSuperAdmin()&amp;&amp;operatorPurviews.size()==0)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LOG.info("此用户:"&nbsp;+&nbsp;OperatorUtil.getLoginName()&nbsp;+&nbsp;"&nbsp;没有任何角色，没有权限执行任何功能");&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;"loginErr";&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;"authorityErr";<br />&nbsp;&nbsp;&nbsp;&nbsp;}</div><br />2.struts2.xml 配置interceptor<br /><br />&nbsp; 2.1 定义自定义拦截器<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->&lt;interceptor&nbsp;name="authorityInterceptor"&nbsp;<span style="color: #0000FF; ">class</span>="com.wasu.eis.authority.AuthorityInterceptor"&nbsp;/&gt;&nbsp;</div>&nbsp; 2.2 加上struts2默认拦截器，形成拦截器栈<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&lt;interceptor-stack&nbsp;name="eisManagerBasicStack"&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;interceptor-ref&nbsp;name="exception"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;interceptor-ref&nbsp;name="alias"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;interceptor-ref&nbsp;name="servletConfig"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;interceptor-ref&nbsp;name="prepare"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;interceptor-ref&nbsp;name="i18n"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;interceptor-ref&nbsp;name="chain"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;interceptor-ref&nbsp;name="debugging"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;interceptor-ref&nbsp;name="profiling"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;interceptor-ref&nbsp;name="scopedModelDriven"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;interceptor-ref&nbsp;name="modelDriven"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;interceptor-ref&nbsp;name="checkbox"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;interceptor-ref&nbsp;name="staticParams"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;interceptor-ref&nbsp;name&nbsp;="fileUploadStack"&nbsp;/&gt;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;interceptor-ref&nbsp;name="params"&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;param&nbsp;name="excludeParams"&gt;dojo\..*&lt;/param&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/interceptor-ref&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;interceptor-ref&nbsp;name="conversionError"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;interceptor-ref&nbsp;name="validation"&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;param&nbsp;name="excludeMethods"&gt;input,back,cancel,browse&lt;/param&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/interceptor-ref&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;interceptor-ref&nbsp;name="workflow"&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;param&nbsp;name="excludeMethods"&gt;input,back,cancel,browse&lt;/param&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/interceptor-ref&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/interceptor-stack&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;interceptor-stack&nbsp;name="authorityInterceptorStack"&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;interceptor-ref&nbsp;name="authorityInterceptor"&nbsp;/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;interceptor-ref&nbsp;name="eisManagerBasicStack"&nbsp;/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/interceptor-stack&gt;</div><br />3.设置为缺省的拦截器<br /><br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->&lt;<span style="color: #0000FF; ">default</span>-interceptor-ref&nbsp;name="authorityInterceptorStack"/&gt;</div><img src ="http://www.blogjava.net/RoyPayne/aggbug/368664.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/RoyPayne/" target="_blank">RoyPayne</a> 2012-01-17 16:35 <a href="http://www.blogjava.net/RoyPayne/archive/2012/01/17/368664.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>spring事务传播属性与隔离级别</title><link>http://www.blogjava.net/RoyPayne/archive/2012/01/05/367919.html</link><dc:creator>RoyPayne</dc:creator><author>RoyPayne</author><pubDate>Thu, 05 Jan 2012 07:25:00 GMT</pubDate><guid>http://www.blogjava.net/RoyPayne/archive/2012/01/05/367919.html</guid><wfw:comment>http://www.blogjava.net/RoyPayne/comments/367919.html</wfw:comment><comments>http://www.blogjava.net/RoyPayne/archive/2012/01/05/367919.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/RoyPayne/comments/commentRss/367919.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/RoyPayne/services/trackbacks/367919.html</trackback:ping><description><![CDATA[<div><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; background-color: #ffffff; ">一、Propagation （事务的传播属性）</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">Propagation ：　　key属性确定代理应该给哪个方法增加事务行为。这样的属性最重要的部份是传播行为。有以下选项可供使用：PROPAGATION_REQUIRED--支持当前事务，如果当前没有事务，就新建一个事务。这是最常见的选择。</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">PROPAGATION_SUPPORTS--支持当前事务，如果当前没有事务，就以非事务方式执行。</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">PROPAGATION_MANDATORY--支持当前事务，如果当前没有事务，就抛出异常。</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">PROPAGATION_REQUIRES_NEW--新建事务，如果当前存在事务，把当前事务挂起。</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作，如果当前存在事务，就把当前事务挂起。</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">PROPAGATION_NEVER--以非事务方式执行，如果当前存在事务，则抛出异常。</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">1： PROPAGATION_REQUIRED</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">加入当前正要执行的事务不在另外一个事务里，那么就起一个新的事务</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">比如说，ServiceB.methodB的事务级别定义为PROPAGATION_REQUIRED, 那么由于执行ServiceA.methodA的时候，</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">ServiceA.methodA已经起了事务，这时调用ServiceB.methodB，ServiceB.methodB看到自己已经运行在ServiceA.methodA</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">的事务内部，就不再起新的事务。而假如ServiceA.methodA运行的时候发现自己没有在事务中，他就会为自己分配一个事务。</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">这样，在ServiceA.methodA或者在ServiceB.methodB内的任何地方出现异常，事务都会被回滚。即使ServiceB.methodB的事务已经被</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">提交，但是ServiceA.methodA在接下来fail要回滚，ServiceB.methodB也要回滚</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">2： PROPAGATION_SUPPORTS</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">如果当前在事务中，即以事务的形式运行，如果当前不再一个事务中，那么就以非事务的形式运行</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">3： PROPAGATION_MANDATORY</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">必须在一个事务中运行。也就是说，他只能被一个父事务调用。否则，他就要抛出异常</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">4： PROPAGATION_REQUIRES_NEW</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">这个就比较绕口了。 比如我们设计ServiceA.methodA的事务级别为PROPAGATION_REQUIRED，ServiceB.methodB的事务级别为PROPAGATION_REQUIRES_NEW，</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">那么当执行到ServiceB.methodB的时候，ServiceA.methodA所在的事务就会挂起，ServiceB.methodB会起一个新的事务，等待ServiceB.methodB的事务完成以后，</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">他才继续执行。他与PROPAGATION_REQUIRED 的事务区别在于事务的回滚程度了。因为ServiceB.methodB是新起一个事务，那么就是存在</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">两个不同的事务。如果ServiceB.methodB已经提交，那么ServiceA.methodA失败回滚，ServiceB.methodB是不会回滚的。如果ServiceB.methodB失败回滚，</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">如果他抛出的异常被ServiceA.methodA捕获，ServiceA.methodA事务仍然可能提交。</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">5： PROPAGATION_NOT_SUPPORTED</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">当前不支持事务。比如ServiceA.methodA的事务级别是PROPAGATION_REQUIRED ，而ServiceB.methodB的事务级别是PROPAGATION_NOT_SUPPORTED ，</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">那么当执行到ServiceB.methodB时，ServiceA.methodA的事务挂起，而他以非事务的状态运行完，再继续ServiceA.methodA的事务。</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">6： PROPAGATION_NEVER</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">不能在事务中运行。假设ServiceA.methodA的事务级别是PROPAGATION_REQUIRED， 而ServiceB.methodB的事务级别是PROPAGATION_NEVER ，</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">那么ServiceB.methodB就要抛出异常了。</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">7： PROPAGATION_NESTED</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">理解Nested的关键是savepoint。他与PROPAGATION_REQUIRES_NEW的区别是，PROPAGATION_REQUIRES_NEW另起一个事务，将会与他的父事务相互独立，</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">而Nested的事务和他的父事务是相依的，他的提交是要等和他的父事务一块提交的。也就是说，如果父事务最后回滚，他也要回滚的。</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">而Nested事务的好处是他有一个savepoint。</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">*****************************************</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">ServiceA {</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">/**</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">* 事务属性配置为 PROPAGATION_REQUIRED</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">*/</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">void methodA() {</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">try {</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">//savepoint</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">ServiceB.methodB(); //PROPAGATION_NESTED 级别</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">} catch (SomeException) {</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">// 执行其他业务, 如 ServiceC.methodC();</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">}</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">}</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">}</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">********************************************</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">也就是说ServiceB.methodB失败回滚，那么ServiceA.methodA也会回滚到savepoint点上，ServiceA.methodA可以选择另外一个分支，比如</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">ServiceC.methodC，继续执行，来尝试完成自己的事务。</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">但是这个事务并没有在EJB标准中定义。</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">Spring事务的隔离级别</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;1. ISOLATION_DEFAULT： 这是一个PlatfromTransactionManager默认的隔离级别，使用数据库默认的事务隔离级别.</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 另外四个与JDBC的隔离级别相对应</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;2. ISOLATION_READ_UNCOMMITTED： 这是事务最低的隔离级别，它充许令外一个事务可以看到这个事务未提交的数据。</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这种隔离级别会产生脏读，不可重复读和幻像读。</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;3. ISOLATION_READ_COMMITTED： 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;4. ISOLATION_REPEATABLE_READ： 这种事务隔离级别可以防止脏读，不可重复读。但是可能出现幻像读。</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 它除了保证一个事务不能读取另一个事务未提交的数据外，还保证了避免下面的情况产生(不可重复读)。</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;5. ISOLATION_SERIALIZABLE 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 除了防止脏读，不可重复读外，还避免了幻像读。</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">什么是脏数据，脏读，不可重复读，幻觉读？</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;脏读: 指当一个事务正在访问数据，并且对数据进行了修改，而这种修改还没有提交到数据库中，这时，</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp; 另外一个事务也访问这个数据，然后使用了这个数据。因为这个数据是还没有提交的数据， 那么另外一</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp; 个事务读到的这个数据是脏数据，依据脏数据所做的操作可能是不正确的。</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;&nbsp; &nbsp;</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;不可重复读: 指在一个事务内，多次读同一数据。在这个事务还没有结束时，另外一个事务也访问该同一数据。</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 那么，在第一个事务中的两次读数据之间，由于第二个事务的修改，那么第一个事务两次读到的数据</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 可能是不一样的。这样就发生了在一个事务内两次读到的数据是不一样的，因此称为是不可重复读。</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;幻觉读: 指当事务不是独立执行时发生的一种现象，例如第一个事务对一个表中的数据进行了修改，这种修改涉及</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 到表中的全部数据行。同时，第二个事务也修改这个表中的数据，这种修改是向表中插入一行新数据。那么，</span><br style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; " /><span style="color: #333333; font-family: Arial; font-size: 14px; line-height: 26px; text-align: left; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行，就好象发生了幻觉一样。</span></div><img src ="http://www.blogjava.net/RoyPayne/aggbug/367919.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/RoyPayne/" target="_blank">RoyPayne</a> 2012-01-05 15:25 <a href="http://www.blogjava.net/RoyPayne/archive/2012/01/05/367919.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>