﻿<?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-byterat-随笔分类-Java Frameworks</title><link>http://www.blogjava.net/byterat/category/16470.html</link><description /><language>zh-cn</language><lastBuildDate>Fri, 30 Mar 2007 09:09:14 GMT</lastBuildDate><pubDate>Fri, 30 Mar 2007 09:09:14 GMT</pubDate><ttl>60</ttl><item><title>(转)spring事务探索</title><link>http://www.blogjava.net/byterat/archive/2007/03/05/101915.html</link><dc:creator>比特鼠</dc:creator><author>比特鼠</author><pubDate>Mon, 05 Mar 2007 06:45:00 GMT</pubDate><guid>http://www.blogjava.net/byterat/archive/2007/03/05/101915.html</guid><wfw:comment>http://www.blogjava.net/byterat/comments/101915.html</wfw:comment><comments>http://www.blogjava.net/byterat/archive/2007/03/05/101915.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/byterat/comments/commentRss/101915.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/byterat/services/trackbacks/101915.html</trackback:ping><description><![CDATA[
		<p>
				<font face="Courier New" size="2">
						<font color="#000000">
								<strong>spring事务探索</strong>
								<br />
								<br />原文出处: </font>
				</font>
				<a href="http://www.javaeye.com/topic/11190">
						<font face="Courier New" color="#000000" size="2">http://www.javaeye.com/topic/11190</font>
				</a>
				<br />
				<br />
		</p>
		<p>
				<font face="Courier New" color="#000000" size="2">spring自建事务管理模块。而且这个事务管理是一个抽象设计，可以应用到很多场合，包括普通的DataSource，jta，jms和hibernate上。</font>
		</p>
		<p>
				<font face="Courier New" color="#000000" size="2">要正确使用spring的事务，首先需要了解spring在事务设计上的一些概念 <br />统观spring事务，围绕着两个核心PlatformTransactionManager和TransactionStatus </font>
		</p>
		<p>
				<font face="Courier New" color="#000000" size="2">PlatformTransactionManager直译过来就是平台相关事务，这里的平台指的是“事务源”，包括刚才我说的DataSource，jta等等。这些无一不是一个事务源。广义的说，凡是可以完成事务性操作的对象，都可以设计出相对应的PlatformTransactionManager，只要这个事务源支持commit，rollback和getTransaction语意。</font>
		</p>
		<p>
				<font face="Courier New" color="#000000" size="2">查看spring代码，可以发现这些manager实现事务，就是调用事务源的事务操作方法</font>
		</p>
		<p>
				<font face="Courier New" color="#000000" size="2">比如</font>
		</p>
		<p>
				<font face="Courier New" color="#000000" size="2">HibernateTransactionManager <br /></font>
		</p>
		<p class="code_title">
				<font face="Courier New" color="#000000" size="2">代码</font>
		</p>
		<div class="code_div">
				<p class="bar">
						<font face="Courier New" color="#000000" size="2">
						</font> </p>
				<div class="dp-highlighter">
						<ol class="dp-j">
								<li class="alt">
										<span>
												<font face="Courier New">
														<font size="2">
																<font color="#000000">
																		<span class="keyword">protected</span>
																		<span> </span>
																		<span class="keyword">void</span>
																		<span> doCommit(DefaultTransactionStatus status) {   </span>
																</font>
														</font>
												</font>
										</span>
								</li>
								<li class="">
										<span>
												<font face="Courier New" color="#000000" size="2">        HibernateTransactionObject txObject = (HibernateTransactionObject) status.getTransaction();   </font>
										</span>
								</li>
								<li class="alt">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>        </span>
																<span class="keyword">if</span>
																<span> (status.isDebug()) {   </span>
														</font>
												</font>
										</font>
								</li>
								<li class="">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>            logger.debug(</span>
																<span class="string">"Committing Hibernate transaction on session ["</span>
																<span> +   </span>
														</font>
												</font>
										</font>
								</li>
								<li class="alt">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>                    txObject.getSessionHolder().getSession() + </span>
																<span class="string">"]"</span>
																<span>);   </span>
														</font>
												</font>
										</font>
								</li>
								<li class="">
										<span>
												<font face="Courier New" color="#000000" size="2">        }   </font>
										</span>
								</li>
								<li class="alt">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>        </span>
																<span class="keyword">try</span>
																<span> {   </span>
														</font>
												</font>
										</font>
								</li>
								<li class="">
										<span>
												<font face="Courier New" color="#000000" size="2">            txObject.getSessionHolder().getTransaction().commit();   </font>
										</span>
								</li>
								<li class="alt">
										<span>
												<font face="Courier New" color="#000000" size="2">        }   </font>
										</span>
								</li>
								<li class="">
										<span>
												<font face="Courier New" color="#000000" size="2">...   </font>
										</span>
								</li>
								<li class="alt">
										<span>
												<font face="Courier New" color="#000000" size="2">  </font>
										</span>
								</li>
								<li class="">
										<span>
												<font face="Courier New" color="#000000" size="2">    }  </font>
										</span>
								</li>
						</ol>
				</div>
		</div>
		<script><![CDATA[ender_code();]]&gt;</script>
		<p>
				<font face="Courier New" color="#000000" size="2">
				</font>
		</p>
		<p>
				<font face="Courier New" color="#000000" size="2">jdbc 的DataSourceTransactionManager <br /></font>
		</p>
		<p class="code_title">
				<font face="Courier New" color="#000000" size="2">代码</font>
		</p>
		<div class="code_div">
				<p class="bar">
						<font face="Courier New" color="#000000" size="2">
						</font> </p>
				<div class="dp-highlighter">
						<ol class="dp-j">
								<li class="alt">
										<span>
												<font face="Courier New">
														<font size="2">
																<font color="#000000">
																		<span class="keyword">protected</span>
																		<span> </span>
																		<span class="keyword">void</span>
																		<span> doCommit(DefaultTransactionStatus status) {   </span>
																</font>
														</font>
												</font>
										</span>
								</li>
								<li class="">
										<span>
												<font face="Courier New" color="#000000" size="2">        DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();   </font>
										</span>
								</li>
								<li class="alt">
										<span>
												<font face="Courier New" color="#000000" size="2">        Connection con = txObject.getConnectionHolder().getConnection();   </font>
										</span>
								</li>
								<li class="">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>        </span>
																<span class="keyword">if</span>
																<span> (status.isDebug()) {   </span>
														</font>
												</font>
										</font>
								</li>
								<li class="alt">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>            logger.debug(</span>
																<span class="string">"Committing JDBC transaction on connection ["</span>
																<span> + con + </span>
																<span class="string">"]"</span>
																<span>);   </span>
														</font>
												</font>
										</font>
								</li>
								<li class="">
										<span>
												<font face="Courier New" color="#000000" size="2">        }   </font>
										</span>
								</li>
								<li class="alt">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>        </span>
																<span class="keyword">try</span>
																<span> {   </span>
														</font>
												</font>
										</font>
								</li>
								<li class="">
										<span>
												<font face="Courier New" color="#000000" size="2">            con.commit();   </font>
										</span>
								</li>
								<li class="alt">
										<span>
												<font face="Courier New" color="#000000" size="2">        }   </font>
										</span>
								</li>
								<li class="">
										<span>
												<font face="Courier New" color="#000000" size="2">        ...   </font>
										</span>
								</li>
								<li class="alt">
										<span>
												<font face="Courier New" color="#000000" size="2">    }  </font>
										</span>
								</li>
						</ol>
				</div>
		</div>
		<script><![CDATA[ender_code();]]&gt;</script>
		<p>
				<font face="Courier New" color="#000000" size="2">
				</font>
		</p>
		<p>
				<font face="Courier New" color="#000000" size="2">那么PlatformTransactionManager以什么依据处理事务呢？ <br />是TransactionStatus <br />查看api发现这个接口有三个方法 <br />isNewTransaction() ，isRollbackOnly()，setRollbackOnly() <br />PlatformTransactionManager就是根据前两个方法决定是否要创建一个新事务，是要递交还是回滚。至于第三个方法是改变事务当前状态的，很多地方都要用到，偏偏PlatformTransactionManager自身好像不怎么用，毕竟事务状态的改变是由程序员代码决定的，不需要一个manager多管闲事。</font>
		</p>
		<p>
				<font face="Courier New" color="#000000" size="2">总结上面所说的，spring的事务由PlatformTransactionManager管理，manager最后调用事务源的方法来实现一个事务过程。而manager通过TransactionStatus 来决定如何实现。 <br /><br />接下去说spring事务中的TransactionTemplate和TransactionInterceptor</font>
		</p>
		<p>
				<font face="Courier New" color="#000000" size="2">TransactionTemplate其实和spring中其他的template的作用类似，起到化简代码的作用，不要被它那么长的名字吓倒了，事实上这个template并不是什么非常核心的对象。如果比较学究派的，可以去看看template设计模式，在此就不再对此赘述了。 <br />为什么要有TransactionTemplate？先来看看如果没有TransactionTemplate，我们的代码该怎么写</font>
		</p>
		<p>
				<font face="Courier New" color="#000000" size="2">先来看看spring reference中的一段代码 <br /></font>
		</p>
		<p class="code_title">
				<font face="Courier New" color="#000000" size="2">代码</font>
		</p>
		<div class="code_div">
				<p class="bar">
						<font face="Courier New" color="#000000" size="2">
						</font> </p>
				<div class="dp-highlighter">
						<ol class="dp-j">
								<li class="alt">
										<span>
												<font face="Courier New">
														<font size="2">
																<font color="#000000">
																		<span>DefaultTransactionDefinition def = </span>
																		<span class="keyword">new</span>
																		<span> DefaultTransactionDefinition()   </span>
																</font>
														</font>
												</font>
										</span>
								</li>
								<li class="">
										<span>
												<font face="Courier New" color="#000000" size="2">def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);   </font>
										</span>
								</li>
								<li class="alt">
										<span>
												<font face="Courier New" color="#000000" size="2">  </font>
										</span>
								</li>
								<li class="">
										<span>
												<font face="Courier New" color="#000000" size="2">TransactionStatus status = transactionManager.getTransaction(def);   </font>
										</span>
								</li>
								<li class="alt">
										<span>
												<font face="Courier New" color="#000000" size="2">  </font>
										</span>
								</li>
								<li class="">
										<span>
										</span>
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span class="keyword">try</span>
																<span> {   </span>
														</font>
												</font>
										</font>
								</li>
								<li class="alt">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>    </span>
																<span class="comment">// execute your business logic here </span>
																<span>  </span>
														</font>
												</font>
										</font>
								</li>
								<li class="">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>} </span>
																<span class="keyword">catch</span>
																<span> (MyException ex) {   </span>
														</font>
												</font>
										</font>
								</li>
								<li class="alt">
										<span>
												<font face="Courier New" color="#000000" size="2">    transactionManager.rollback(status);   </font>
										</span>
								</li>
								<li class="">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>    </span>
																<span class="keyword">throw</span>
																<span> ex;   </span>
														</font>
												</font>
										</font>
								</li>
								<li class="alt">
										<span>
												<font face="Courier New" color="#000000" size="2">}   </font>
										</span>
								</li>
								<li class="">
										<span>
												<font face="Courier New" color="#000000" size="2">transactionManager.commit(status);  </font>
										</span>
								</li>
						</ol>
				</div>
		</div>
		<script><![CDATA[ender_code();]]&gt;</script>
		<p>
				<br />
				<font face="Courier New" color="#000000" size="2">这是直接使用transactionManager的例子，可以看到真正执行business logic 的地方是在try当中那段，前后的代码都是为了完成事务管理的。如果每个business logic都要写上那么一段，我肯定是疯了。我们翻出TransactionTemplate的代码看看他怎么化简了我们的代码 </font>
		</p>
		<p>
				<font face="Courier New" color="#000000" size="2">
				</font>
		</p>
		<p>
				<font face="Courier New" color="#000000" size="2">
				</font>
		</p>
		<p class="code_title">
				<font face="Courier New" color="#000000" size="2">代码</font>
		</p>
		<div class="code_div">
				<p class="bar">
						<font face="Courier New" color="#000000" size="2">
						</font> </p>
				<div class="dp-highlighter">
						<ol class="dp-j">
								<li class="alt">
										<span>
												<font face="Courier New">
														<font size="2">
																<font color="#000000">
																		<span class="keyword">public</span>
																		<span> Object execute(TransactionCallback action) </span>
																		<span class="keyword">throws</span>
																		<span> TransactionException {   </span>
																</font>
														</font>
												</font>
										</span>
								</li>
								<li class="">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>        TransactionStatus status = </span>
																<span class="keyword">this</span>
																<span>.transactionManager.getTransaction(</span>
																<span class="keyword">this</span>
																<span>);   </span>
														</font>
												</font>
										</font>
								</li>
								<li class="alt">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>        Object result = </span>
																<span class="keyword">null</span>
																<span>;   </span>
														</font>
												</font>
										</font>
								</li>
								<li class="">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>        </span>
																<span class="keyword">try</span>
																<span> {   </span>
														</font>
												</font>
										</font>
								</li>
								<li class="alt">
										<span>
												<font face="Courier New" color="#000000" size="2">            result = action.doInTransaction(status);   </font>
										</span>
								</li>
								<li class="">
										<span>
												<font face="Courier New" color="#000000" size="2">        }   </font>
										</span>
								</li>
								<li class="alt">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>        </span>
																<span class="keyword">catch</span>
																<span> (RuntimeException ex) {   </span>
														</font>
												</font>
										</font>
								</li>
								<li class="">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>            </span>
																<span class="comment">// transactional code threw application exception -&gt; rollback </span>
																<span>  </span>
														</font>
												</font>
										</font>
								</li>
								<li class="alt">
										<span>
												<font face="Courier New" color="#000000" size="2">            rollbackOnException(status, ex);   </font>
										</span>
								</li>
								<li class="">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>            </span>
																<span class="keyword">throw</span>
																<span> ex;   </span>
														</font>
												</font>
										</font>
								</li>
								<li class="alt">
										<span>
												<font face="Courier New" color="#000000" size="2">        }   </font>
										</span>
								</li>
								<li class="">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>        </span>
																<span class="keyword">catch</span>
																<span> (Error err) {   </span>
														</font>
												</font>
										</font>
								</li>
								<li class="alt">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>            </span>
																<span class="comment">// transactional code threw error -&gt; rollback </span>
																<span>  </span>
														</font>
												</font>
										</font>
								</li>
								<li class="">
										<span>
												<font face="Courier New" color="#000000" size="2">            rollbackOnException(status, err);   </font>
										</span>
								</li>
								<li class="alt">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>            </span>
																<span class="keyword">throw</span>
																<span> err;   </span>
														</font>
												</font>
										</font>
								</li>
								<li class="">
										<span>
												<font face="Courier New" color="#000000" size="2">        }   </font>
										</span>
								</li>
								<li class="alt">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>        </span>
																<span class="keyword">this</span>
																<span>.transactionManager.commit(status);   </span>
														</font>
												</font>
										</font>
								</li>
								<li class="">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>        </span>
																<span class="keyword">return</span>
																<span> result;   </span>
														</font>
												</font>
										</font>
								</li>
								<li class="alt">
										<span>
												<font face="Courier New" color="#000000" size="2">    }  </font>
										</span>
								</li>
						</ol>
				</div>
		</div>
		<script><![CDATA[ender_code();]]&gt;</script>
		<p>
				<font face="Courier New" color="#000000" size="2">
				</font>
		</p>
		<p>
				<font face="Courier New" color="#000000" size="2">同上面的代码如出一辙，前后是事务处理代码，当中那段result = action.doInTransaction(status);是我们的应用代码。至于action是什么，全看各位的需要了。但是有一点要主要，如果利用TransactionTemplate，那么他不管你扔出什么异常都会回滚事务，但是回滚的是哪个事务呢？继续挖代码 <br /></font>
		</p>
		<p class="code_title">
				<font face="Courier New" color="#000000" size="2">代码</font>
		</p>
		<div class="code_div">
				<p class="bar">
						<font face="Courier New" color="#000000" size="2">
						</font> </p>
				<div class="dp-highlighter">
						<ol class="dp-j">
								<li class="alt">
										<span>
												<font face="Courier New">
														<font size="2">
																<font color="#000000">
																		<span class="keyword">private</span>
																		<span> </span>
																		<span class="keyword">void</span>
																		<span> rollbackOnException(TransactionStatus status, Throwable ex) </span>
																		<span class="keyword">throws</span>
																		<span> TransactionException {   </span>
																</font>
														</font>
												</font>
										</span>
								</li>
								<li class="">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>        </span>
																<span class="keyword">if</span>
																<span> (logger.isDebugEnabled()) {   </span>
														</font>
												</font>
										</font>
								</li>
								<li class="alt">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>            logger.debug(</span>
																<span class="string">"Initiating transaction rollback on application exception"</span>
																<span>, ex);   </span>
														</font>
												</font>
										</font>
								</li>
								<li class="">
										<span>
												<font face="Courier New" color="#000000" size="2">        }   </font>
										</span>
								</li>
								<li class="alt">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>        </span>
																<span class="keyword">try</span>
																<span> {   </span>
														</font>
												</font>
										</font>
								</li>
								<li class="">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>            </span>
																<span class="keyword">this</span>
																<span>.transactionManager.rollback(status);   </span>
														</font>
												</font>
										</font>
								</li>
								<li class="alt">
										<span>
												<font face="Courier New" color="#000000" size="2">        }   </font>
										</span>
								</li>
								<li class="">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>        </span>
																<span class="keyword">catch</span>
																<span> (RuntimeException ex2) {   </span>
														</font>
												</font>
										</font>
								</li>
								<li class="alt">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>            logger.error(</span>
																<span class="string">"Application exception overridden by rollback exception"</span>
																<span>, ex);   </span>
														</font>
												</font>
										</font>
								</li>
								<li class="">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>            </span>
																<span class="keyword">throw</span>
																<span> ex2;   </span>
														</font>
												</font>
										</font>
								</li>
								<li class="alt">
										<span>
												<font face="Courier New" color="#000000" size="2">        }   </font>
										</span>
								</li>
								<li class="">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>        </span>
																<span class="keyword">catch</span>
																<span> (Error err) {   </span>
														</font>
												</font>
										</font>
								</li>
								<li class="alt">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>            logger.error(</span>
																<span class="string">"Application exception overridden by rollback error"</span>
																<span>, ex);   </span>
														</font>
												</font>
										</font>
								</li>
								<li class="">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>            </span>
																<span class="keyword">throw</span>
																<span> err;   </span>
														</font>
												</font>
										</font>
								</li>
								<li class="alt">
										<span>
												<font face="Courier New" color="#000000" size="2">        }   </font>
										</span>
								</li>
								<li class="">
										<span>
												<font face="Courier New" color="#000000" size="2">    }  </font>
										</span>
								</li>
						</ol>
				</div>
		</div>
		<script><![CDATA[ender_code();]]&gt;</script>
		<p>
				<br />
				<font face="Courier New" color="#000000" size="2">真相大白，是对template所持有的某个transactionManager进行回滚。所以如果你的应用代码用的是事务源a的一些资源，比如到服务器a的一个datasource，但是你的transactionManager管理的是另一些资源，比如服务器b的一个datasource，代码铁定不会正常运行 </font>
		</p>
		<p>
				<font face="Courier New" color="#000000" size="2">
				</font>
		</p>
		<p>
				<font face="Courier New" color="#000000" size="2">特别是在一些多事务源的程序里，这点千万不能搞错。如果多个事务源之间要完成全局事务，还是老老实实用分布式事务管理服务吧（jta）</font>
		</p>
		<p>
				<font face="Courier New" color="#000000" size="2">那么TransactionInterceptor是干什么的？这个是spring 的声明式事务的支持方式。因为用TransactionTemplate要硬编码，而且调整事务策略很麻烦（不是说不能调。举个例子原来程序抛出异常A需要回滚，现在不需要要，我就可以把a catch吃掉。这时候template就不会回滚了。但是每次调整都要重写编码。）而用TransactionInterceptor就可以将这些调整写在配置中。我们再来挖TransactionInterceptor的代码</font>
		</p>
		<p>
				<font face="Courier New" color="#000000" size="2">
				</font>
		</p>
		<p class="code_title">
				<font face="Courier New" color="#000000" size="2">代码</font>
		</p>
		<div class="code_div">
				<p class="bar">
						<font face="Courier New" color="#000000" size="2">
						</font> </p>
				<div class="dp-highlighter">
						<ol class="dp-j">
								<li class="alt">
										<span>
												<font face="Courier New">
														<font size="2">
																<font color="#000000">
																		<span class="keyword">public</span>
																		<span> Object invoke(MethodInvocation invocation) </span>
																		<span class="keyword">throws</span>
																		<span> Throwable {   </span>
																</font>
														</font>
												</font>
										</span>
								</li>
								<li class="">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>        </span>
																<span class="comment">// Work out the target class: may be null. </span>
																<span>  </span>
														</font>
												</font>
										</font>
								</li>
								<li class="alt">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>        </span>
																<span class="comment">// The TransactionAttributeSource should be passed the target class </span>
																<span>  </span>
														</font>
												</font>
										</font>
								</li>
								<li class="">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>        </span>
																<span class="comment">// as well as the method, which may be from an interface </span>
																<span>  </span>
														</font>
												</font>
										</font>
								</li>
								<li class="alt">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>        Class targetClass = (invocation.getThis() != </span>
																<span class="keyword">null</span>
																<span>) ? invocation.getThis().getClass() : </span>
																<span class="keyword">null</span>
																<span>;   </span>
														</font>
												</font>
										</font>
								</li>
								<li class="">
										<span>
												<font face="Courier New" color="#000000" size="2">           </font>
										</span>
								</li>
								<li class="alt">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>        </span>
																<span class="comment">// Create transaction if necessary </span>
																<span>  </span>
														</font>
												</font>
										</font>
								</li>
								<li class="">
										<span>
												<font face="Courier New" color="#000000" size="2">        TransactionInfo txInfo = createTransactionIfNecessary(invocation.getMethod(), targetClass);   </font>
										</span>
								</li>
								<li class="alt">
										<span>
												<font face="Courier New" color="#000000" size="2">  </font>
										</span>
								</li>
								<li class="">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>        Object retVal = </span>
																<span class="keyword">null</span>
																<span>;   </span>
														</font>
												</font>
										</font>
								</li>
								<li class="alt">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>        </span>
																<span class="keyword">try</span>
																<span> {   </span>
														</font>
												</font>
										</font>
								</li>
								<li class="">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>            </span>
																<span class="comment">// This is an around advice. </span>
																<span>  </span>
														</font>
												</font>
										</font>
								</li>
								<li class="alt">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>            </span>
																<span class="comment">// Invoke the next interceptor in the chain. </span>
																<span>  </span>
														</font>
												</font>
										</font>
								</li>
								<li class="">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>            </span>
																<span class="comment">// This will normally result in a target object being invoked. </span>
																<span>  </span>
														</font>
												</font>
										</font>
								</li>
								<li class="alt">
										<span>
												<font face="Courier New" color="#000000" size="2">            retVal = invocation.proceed();   </font>
										</span>
								</li>
								<li class="">
										<span>
												<font face="Courier New" color="#000000" size="2">        }   </font>
										</span>
								</li>
								<li class="alt">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>        </span>
																<span class="keyword">catch</span>
																<span> (Throwable ex) {   </span>
														</font>
												</font>
										</font>
								</li>
								<li class="">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>            </span>
																<span class="comment">// target invocation exception </span>
																<span>  </span>
														</font>
												</font>
										</font>
								</li>
								<li class="alt">
										<span>
												<font face="Courier New" color="#000000" size="2">            doCloseTransactionAfterThrowing(txInfo, ex);   </font>
										</span>
								</li>
								<li class="">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>            </span>
																<span class="keyword">throw</span>
																<span> ex;   </span>
														</font>
												</font>
										</font>
								</li>
								<li class="alt">
										<span>
												<font face="Courier New" color="#000000" size="2">        }   </font>
										</span>
								</li>
								<li class="">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>        </span>
																<span class="keyword">finally</span>
																<span> {   </span>
														</font>
												</font>
										</font>
								</li>
								<li class="alt">
										<span>
												<font face="Courier New" color="#000000" size="2">            doFinally(txInfo);   </font>
										</span>
								</li>
								<li class="">
										<span>
												<font face="Courier New" color="#000000" size="2">        }   </font>
										</span>
								</li>
								<li class="alt">
										<span>
												<font face="Courier New" color="#000000" size="2">        doCommitTransactionAfterReturning(txInfo);   </font>
										</span>
								</li>
								<li class="">
										<span>
												<font face="Courier New" color="#000000" size="2">  </font>
										</span>
								</li>
								<li class="alt">
										<font face="Courier New">
												<font size="2">
														<font color="#000000">
																<span>        </span>
																<span class="keyword">return</span>
																<span> retVal;   </span>
														</font>
												</font>
										</font>
								</li>
								<li class="">
										<span>
												<font face="Courier New" color="#000000" size="2">    }  </font>
										</span>
								</li>
						</ol>
				</div>
		</div>
		<script><![CDATA[ender_code();]]&gt;</script>
		<p>
				<br />
				<font face="Courier New" color="#000000" size="2">万变不离其宗。 </font>
		</p>
		<p>
				<font face="Courier New" color="#000000" size="2">
				</font>
		</p>
		<p>
				<font face="Courier New" color="#000000" size="2">所以使用spring的事务管理需要作这些事 <br />1，设置好事务源，比如DataSource，hibernate的session。如果有多个事务源要考虑他们之间是否有全局事务，如果有，老老实实用jta，否则就需要自己写一个manager了 <br />2，设置manager，根据你的事务源选择对应的PlatformTransactionManager <br />3，选择实现事物的方式，用template还是interceptor。用template代码直观点，但是template所管辖的manager和你应用代码所用的事务源要一致。如果用interceptor千万注意，一定要调用interceptor那个bean，而不是原始的那个target。在坛子上我已经看到至少有两个朋友说spring事物不起作用，从配置和代码上看都正确，这时要好好查查，调用的bean是哪一个。 <br />4，这个是设计问题了，推荐事务处于一个较高层次，比如service上的某个函数，而底层的dao可以不考虑事务，否则可能会出现事务嵌套，增加程序复杂度。</font>
		</p>
<img src ="http://www.blogjava.net/byterat/aggbug/101915.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/byterat/" target="_blank">比特鼠</a> 2007-03-05 14:45 <a href="http://www.blogjava.net/byterat/archive/2007/03/05/101915.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>今年的技术规划! </title><link>http://www.blogjava.net/byterat/archive/2007/02/02/97572.html</link><dc:creator>比特鼠</dc:creator><author>比特鼠</author><pubDate>Fri, 02 Feb 2007 07:28:00 GMT</pubDate><guid>http://www.blogjava.net/byterat/archive/2007/02/02/97572.html</guid><wfw:comment>http://www.blogjava.net/byterat/comments/97572.html</wfw:comment><comments>http://www.blogjava.net/byterat/archive/2007/02/02/97572.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/byterat/comments/commentRss/97572.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/byterat/services/trackbacks/97572.html</trackback:ping><description><![CDATA[
		<p>
				<font face="Courier New" size="2">2007年已经过去一个月了, 还没有制定今年的规划, 现在是时候了! <br /><br />争取掌握以下技术:<br /><br />1. Ruby On Rails <br />进一步学习ruby的语法和语义，最好能深入到解释器一层看看有些特性是怎么实现的。<br /><br />2、Spring AOP 及 AspectJ <br />个人觉得Spring 2.0和AspectJ的结合，有很多潜力，值得深入挖掘。<br /><br />3. Web Service<br /><br />4. Java JPA<br /><br />5. Role-Based Access Control , Acegi<br />buaawhl推荐的， <br /></font>
				<a href="http://csrc.nist.gov/rbac/" target="blank">
						<font face="Courier New" size="2">http://csrc.nist.gov/rbac/</font>
				</a>
				<font face="Courier New" size="2">
						<br />
				</font>
				<a href="http://www.amazon.com/Role-Based-Access-Control-David-Ferraiolo/dp/1580533701/sr=1-1/qid=1161828835/ref=pd_bbs_1/002-1138304-7372032?ie=UTF8&amp;s=books" target="blank">
						<font face="Courier New" size="2">http://www.amazon.com/Role-Based-Access-Control-David-Ferraiolo/dp/1580533701/sr=1-1/qid=1161828835/ref=pd_bbs_1/002-1138304-7372032?ie=UTF8&amp;s=books</font>
				</a>
		</p>
		<p>
				<font face="Courier New" size="2">下一个项目的权限管理会比较复杂，以前没学过这方面的知识。从Acegi开始吧，如果够用最好。<br /><br />6. JBoss JBoss的Cache，AppServer的cluster方面是我比较感兴趣的地方，想尝试一下JBoss应用服务器<br /><br />7. 满足一定条件(比如: 并发达1000个请求)框架Web Application群集部署</font>
		</p>
<img src ="http://www.blogjava.net/byterat/aggbug/97572.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/byterat/" target="_blank">比特鼠</a> 2007-02-02 15:28 <a href="http://www.blogjava.net/byterat/archive/2007/02/02/97572.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于Spring属性编辑器详解(转)</title><link>http://www.blogjava.net/byterat/archive/2007/01/20/95083.html</link><dc:creator>比特鼠</dc:creator><author>比特鼠</author><pubDate>Sat, 20 Jan 2007 13:21:00 GMT</pubDate><guid>http://www.blogjava.net/byterat/archive/2007/01/20/95083.html</guid><wfw:comment>http://www.blogjava.net/byterat/comments/95083.html</wfw:comment><comments>http://www.blogjava.net/byterat/archive/2007/01/20/95083.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/byterat/comments/commentRss/95083.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/byterat/services/trackbacks/95083.html</trackback:ping><description><![CDATA[
		<div style="MARGIN-TOP: 10px; MARGIN-LEFT: 15px">
				<table width="100%">
						<tbody>
								<tr>
										<td>
												<p>
														<font face="Courier New">
																<font size="2">
																		<strong>关于Spring属性编辑器详解</strong>
																		<br />
																		<br />原文出处： </font>
														</font>
														<a href="http://stamen.javaeye.com/blog/24660">
																<font face="Courier New" size="2">http://stamen.javaeye.com/blog/24660 </font>
														</a>
														<br />
														<br />
														<font face="Courier New" size="2">最近刚在研究Spring的编辑器，发现很有意思，刚好galaxystar起了一个这样贴，我想对PropertyEditor作一个详细的整理会对大家有益，特定启了这个新帖。 <br /><br />所谓的PropertyEditor，顾名思义，就是属性编辑器。由于Bean属性通过配置文档以字符串了方式为属性赋值，所以必须有一个“东东”负责将这个字符串转换为属性的直接对象，如属性的类型为int，那么编辑器要做的工作就是int i = Integer.parseInt("1"); <br />Spring为一般的属性类型提供了默认的编辑器，BeanWrapperImpl是Spring框架中重要的类，它负责对注入的Bean进行包装化的管理，常见属性类型对应的编辑器即在该类中通过以下代码定义： <br /><br /></font>
												</p>
												<div class="code_title">
														<font face="Courier New" size="2">代码 </font>
												</div>
												<div class="code_div">
														<textarea class="java" name="code" rows="15" cols="100">private void registerDefaultEditors()
    {
        // Simple editors, without parameterization capabilities.
        // The JDK does not contain a default editor for any of these target types.
        this.defaultEditors.put(byte[].class, new ByteArrayPropertyEditor());
        this.defaultEditors.put(Class.class, new ClassEditor());
        this.defaultEditors.put(File.class, new FileEditor());
        this.defaultEditors.put(InputStream.class, new InputStreamEditor());
        this.defaultEditors.put(Locale.class, new LocaleEditor());
        this.defaultEditors.put(Properties.class, new PropertiesEditor());
        this.defaultEditors.put(Resource[].class,
                                new ResourceArrayPropertyEditor());
        this.defaultEditors.put(String[].class, new StringArrayPropertyEditor());
        this.defaultEditors.put(URL.class, new URLEditor());

        // Default instances of collection editors.
        // Can be overridden by registering custom instances of those as custom editors.
        this.defaultEditors.put(Collection.class,
                                new CustomCollectionEditor(Collection.class));
        this.defaultEditors.put(Set.class, new CustomCollectionEditor(Set.class));
        this.defaultEditors.put(SortedSet.class,
                                new CustomCollectionEditor(SortedSet.class));
        this.defaultEditors.put(List.class, new CustomCollectionEditor(List.class));

        // Default instances of character and boolean editors.
        // Can be overridden by registering custom instances of those as custom editors.
        PropertyEditor characterEditor = new CharacterEditor(false);
        PropertyEditor booleanEditor = new CustomBooleanEditor(false);

        // The JDK does not contain a default editor for char!
        this.defaultEditors.put(char.class, characterEditor);
        this.defaultEditors.put(Character.class, characterEditor);

        // Spring's CustomBooleanEditor accepts more flag values than the JDK's default editor.
        this.defaultEditors.put(boolean.class, booleanEditor);
        this.defaultEditors.put(Boolean.class, booleanEditor);

        // The JDK does not contain default editors for number wrapper types!
        // Override JDK primitive number editors with our own CustomNumberEditor.
        PropertyEditor byteEditor = new CustomNumberEditor(Byte.class, false);
        PropertyEditor shortEditor = new CustomNumberEditor(Short.class, false);
        PropertyEditor integerEditor = new CustomNumberEditor(Integer.class, false);
        PropertyEditor longEditor = new CustomNumberEditor(Long.class, false);
        PropertyEditor floatEditor = new CustomNumberEditor(Float.class, false);
        PropertyEditor doubleEditor = new CustomNumberEditor(Double.class, false);

        this.defaultEditors.put(byte.class, byteEditor);
        this.defaultEditors.put(Byte.class, byteEditor);

        this.defaultEditors.put(short.class, shortEditor);
        this.defaultEditors.put(Short.class, shortEditor);

        this.defaultEditors.put(int.class, integerEditor);
        this.defaultEditors.put(Integer.class, integerEditor);

        this.defaultEditors.put(long.class, longEditor);
        this.defaultEditors.put(Long.class, longEditor);

        this.defaultEditors.put(float.class, floatEditor);
        this.defaultEditors.put(Float.class, floatEditor);

        this.defaultEditors.put(double.class, doubleEditor);
        this.defaultEditors.put(Double.class, doubleEditor);

        this.defaultEditors.put(BigDecimal.class,
                                new CustomNumberEditor(BigDecimal.class, false));
        this.defaultEditors.put(BigInteger.class,
                                new CustomNumberEditor(BigInteger.class, false));
    }
</textarea>
														<font face="Courier New" size="2">
														</font>
												</div>
												<script><![CDATA[ender_code();]]&gt;</script>
												<br />
												<font face="Courier New" size="2">但是，并非Bean的属性都是这些常见的类型，如果你的Bean需要注入一个自定义类型的属性，而又想享受IoC的好处，那么就只得自己开干，提供一个自定义的PropertyEditor了。 <br />下面，分几个步骤来说明，定义一个自定义PropertyEditor的过程。 <br />1)首先，碰到的问题即是，要如何编辑自己的PropertyEditor,其实需要了解一点java.beans包的知识，在该包中，有一个java.beans.PropertyEditor的接口，它定义了一套接口方法（12个），即通过这些方法如何将一个String变成内部的一个对象，这两个方法是比较重要的： <br />a)setValue(Object value) 直接设置一个对象，一般不直接用该方法设置属性对象 <br />b)setAsText(String text) 通过一个字符串来构造对象，一般在此方法中解析字符串，将构造一个 <br />类对象，调用setValue(Object)来完成属性对象设置操作。 <br /><br />2)实现所有的接口方法是麻烦的，java.beans.PropertyEditorSupport 适时登场，一般情况下，我们通过扩展这个方便类即可。 </font>
												<p>
												</p>
												<p>
														<font face="Courier New" size="2">3)编写完后，就是在Spring配置文件中注册该属性类型编辑器的问题，Spring提供了专门的注册工具类 <br />org.springframework.beans.factory.config.CustomEditorConfigurer，它负责将属性类型和 <br />属性编辑器关联起来。到时BeanFactory注入Bean的属性时，即会在注册表中查找属性类型对应的编辑器。 </font>
												</p>
												<p>
														<font face="Courier New" size="2">下面给出一个小例子，例子先作一个简单描述： <br />1)Person 需要进行属性注入的Bean，有两个属性 一个是name,一个是address Address是一个类 <br />2)Address Person的属性类型，本身有3个属性。 <br />3)AddressPropertyEditor Address类型对应的属性编辑器。 <br /><br />开工： <br />1.Person.java <br /></font>
												</p>
												<div class="code_title">
														<font face="Courier New" size="2">代码 </font>
												</div>
												<div class="code_div">
														<textarea class="java" name="code" rows="15" cols="100">package com.stamen.propedit;

import org.apache.commons.lang.builder.ToStringBuilder;

public class Person {
	private String name;

	private Address address;

	public Address getAddress() {
		return address;
	}

	public void setAddress(Address address) {
		this.address = address;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
    public String toString() {
    	return ToStringBuilder.reflectionToString(this);
    }
 } 
</textarea>
														<font face="Courier New" size="2">
														</font>
												</div>
												<script><![CDATA[ender_code();]]&gt;</script>
												<br />
												<font face="Courier New" size="2">2.Address.java <br /></font>
												<div class="code_title">
														<font face="Courier New" size="2">代码 </font>
												</div>
												<div class="code_div">
														<textarea class="java" name="code" rows="15" cols="100">package com.stamen.propedit;
import org.apache.commons.lang.builder.ToStringBuilder;
public class Address {
	private String street;

	private String doorNum;

	private String postCode;

	public String getDoorNum() {
		return doorNum;
	}

	public void setDoorNum(String doorNum) {
		this.doorNum = doorNum;
	}

	public String getPostCode() {
		return postCode;
	}

	public void setPostCode(String postCode) {
		this.postCode = postCode;
	}

	public String getStreet() {
		return street;
	}

	public void setStreet(String street) {
		this.street = street;
	}
	
    public String toString() {
    	return ToStringBuilder.reflectionToString(this);
    }

}
 </textarea>
														<font face="Courier New" size="2">
														</font>
												</div>
												<script><![CDATA[ender_code();]]&gt;</script>
												<br />
												<br />
												<font face="Courier New" size="2">AddressPropertyEditor.java <br /></font>
												<div class="code_title">
														<font face="Courier New" size="2">代码 </font>
												</div>
												<div class="code_div">
														<textarea class="java" name="code" rows="15" cols="100">package com.stamen.propedit;

import java.beans.PropertyEditorSupport;
import java.util.Date;

import org.springframework.util.StringUtils;
public class AddressPropertyEditor extends PropertyEditorSupport{
	//支持的格式为 streeValue,doorNumValue,postCode
	public void setAsText(String text)
	{
		System.out.println("使用自己的编辑器。");
		if (text == null || !StringUtils.hasText(text)) {
			throw new IllegalArgumentException("老大，不能为空啊！");
		}
		else
		{
			String[] strArr = StringUtils.tokenizeToStringArray(text,",");
			Address add = new Address();
			add.setStreet(strArr[0]);
			add.setDoorNum(strArr[1]);
			add.setPostCode(strArr[2]);
			setValue(add);
		}
	}
	
    public String getAsText()
    {
    	Address add = (Address)getValue();
    	return ""+add;
    }
}
 </textarea>
														<font face="Courier New" size="2">
														</font>
												</div>
												<script><![CDATA[ender_code();]]&gt;</script>
												<p>
														<font face="Courier New" size="2">
														</font>
												</p>
												<p>
														<font face="Courier New" size="2">打开Spring配置文件，添上这两个配置项： <br /></font>
												</p>
												<div class="code_title">
														<font face="Courier New" size="2">代码 </font>
												</div>
												<div class="code_div">
														<textarea class="xml" name="code" rows="15" cols="100">   &lt;bean id="customEditorConfigurer"  class="org.springframework.beans.factory.config.CustomEditorConfigurer"&gt;
   &lt;property name="customEditors"&gt;
     &lt;map&gt;
       &lt;entry key="com.stamen.propedit.Address"&gt; &lt;!-- key为需要转换的类 --&gt;
         &lt;bean class="com.stamen.propedit.AddressPropertyEditor"/&gt; &lt;!--对应的转换类 --&gt;
       &lt;/entry&gt;
     &lt;/map&gt;
   &lt;/property&gt;
 &lt;/bean&gt;

  &lt;bean id="person" class="com.stamen.propedit.Person"&gt;
     &lt;property name="name" value="Tom"/&gt;
     &lt;property name="address" value="朝阳区,Soho 1601,010101"/&gt;
  &lt;/bean&gt;
</textarea>
														<font face="Courier New" size="2">
														</font>
												</div>
												<p>
														<font face="Courier New" size="2">
														</font> </p>
										</td>
								</tr>
						</tbody>
				</table>
		</div>
		<font face="Courier New" size="2">下面是我自己写的日期转换类：<br /></font>
		<textarea class="java" name="code" rows="15" cols="100">package com.lt.resource.propertyeditor;

import java.beans.PropertyEditorSupport;
import java.text.SimpleDateFormat;

import org.springframework.util.StringUtils;

public class DatePropertyEditor extends PropertyEditorSupport {
	private String format = "yyyy-MM-dd"; //缺省
	
	public void setFormat(String format) {
		this.format = format;
	}

	public void setAsText(String text) throws IllegalArgumentException {
		if (text != null || StringUtils.hasText(text)) {
	        setValue(new SimpleDateFormat(this.format).format(text));
		} 
	}

}
</textarea>
		<br />
		<font face="Courier New" size="2">我的配置：<br /></font>
		<textarea class="java" name="code" rows="15" cols="100">	&lt;bean id="customEditorConfigurer" class="org.springframework.beans.factory.config.CustomEditorConfigurer"&gt;
  		&lt;property name="customEditors"&gt;
    		&lt;map&gt;
      			&lt;entry key="java.util.Date"&gt;
        			&lt;bean class="com.lt.resource.propertyeditor.DatePropertyEditor"&gt;
        				&lt;property name="format" value="yyyy年MM月dd日 HH时mm分ss秒" /&gt;  
        			&lt;/bean&gt;
      			&lt;/entry&gt;
   			&lt;/map&gt;
  		&lt;/property&gt;
	&lt;/bean&gt;</textarea>
<img src ="http://www.blogjava.net/byterat/aggbug/95083.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/byterat/" target="_blank">比特鼠</a> 2007-01-20 21:21 <a href="http://www.blogjava.net/byterat/archive/2007/01/20/95083.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>javascript小技巧&amp;&amp;JavaScript[对象.属性]集锦 [转载了多篇] </title><link>http://www.blogjava.net/byterat/archive/2007/01/19/94961.html</link><dc:creator>比特鼠</dc:creator><author>比特鼠</author><pubDate>Fri, 19 Jan 2007 08:51:00 GMT</pubDate><guid>http://www.blogjava.net/byterat/archive/2007/01/19/94961.html</guid><wfw:comment>http://www.blogjava.net/byterat/comments/94961.html</wfw:comment><comments>http://www.blogjava.net/byterat/archive/2007/01/19/94961.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/byterat/comments/commentRss/94961.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/byterat/services/trackbacks/94961.html</trackback:ping><description><![CDATA[Error convertoring HTML to XHTML: System.ArgumentException: Cannot have ']]&gt;' inside an XML CDATA block.
   at System.Xml.XmlTextWriter.WriteCData(String text)
   at System.Xml.XmlWriter.WriteNode(XmlReader reader, Boolean defattr)
   at FreeTextBoxControls.Support.Formatter.HtmlToXhtml(String input)<img src ="http://www.blogjava.net/byterat/aggbug/94961.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/byterat/" target="_blank">比特鼠</a> 2007-01-19 16:51 <a href="http://www.blogjava.net/byterat/archive/2007/01/19/94961.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(转载)OpenSessionInView模式</title><link>http://www.blogjava.net/byterat/archive/2007/01/19/94943.html</link><dc:creator>比特鼠</dc:creator><author>比特鼠</author><pubDate>Fri, 19 Jan 2007 07:33:00 GMT</pubDate><guid>http://www.blogjava.net/byterat/archive/2007/01/19/94943.html</guid><wfw:comment>http://www.blogjava.net/byterat/comments/94943.html</wfw:comment><comments>http://www.blogjava.net/byterat/archive/2007/01/19/94943.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/byterat/comments/commentRss/94943.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/byterat/services/trackbacks/94943.html</trackback:ping><description><![CDATA[
		<h2>
				<font face="Courier New" size="2">原文出自：</font>
				<a href="/waterye/archive/2005/08/23/10836.aspx">
						<font face="Courier New" size="2">http://www.blogjava.net/waterye/archive/2005/08/23/10836.aspx</font>
				</a>
		</h2>
		<h2>
				<a id="viewpost1_TitleUrl" href="/waterye/archive/2005/08/23/10836.html">
						<font face="Courier New" size="2">OpenSessionInView模式</font>
				</a>
				<font face="Courier New" size="2">
				</font>
		</h2>
		<font face="Courier New" size="2">Spring+Hibernate中，  集合映射如果使用lazy="true"， 当PO传到View层时， 出现未初始化session已关闭的错误，只能在dao先初始化 </font>
		<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
				<span style="COLOR: #000000">
						<font face="Courier New" size="2">parent.getChilds().size();</font>
				</span>
		</div>
		<br />
		<font face="Courier New" size="2">Spring提供Open Session In View来解决这个问题, 有两种方式<br />1. Interceptor </font>
		<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
				<font face="Courier New">
						<font size="2">
								<span style="COLOR: #008000">    &lt;!--</span>
								<span style="COLOR: #008000"> =========== OpenSession In View pattern ==============</span>
								<span style="COLOR: #008000">--&gt;</span>
						</font>
				</font>
				<span style="COLOR: #000000">
						<br />
						<font face="Courier New" size="2">    </font>
				</span>
				<font face="Courier New">
						<font size="2">
								<span style="COLOR: #0000ff">&lt;</span>
								<span style="COLOR: #800000">bean </span>
								<span style="COLOR: #ff0000">id</span>
								<span style="COLOR: #0000ff">="openSessionInViewInterceptor"</span>
						</font>
				</font>
				<span style="COLOR: #ff0000">
						<br />
						<font face="Courier New" size="2">          class</font>
				</span>
				<font face="Courier New">
						<font size="2">
								<span style="COLOR: #0000ff">="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor"</span>
								<span style="COLOR: #0000ff">&gt;</span>
						</font>
				</font>
				<span style="COLOR: #000000">
						<br />
						<font face="Courier New" size="2">        </font>
				</span>
				<font face="Courier New">
						<font size="2">
								<span style="COLOR: #0000ff">&lt;</span>
								<span style="COLOR: #800000">property </span>
								<span style="COLOR: #ff0000">name</span>
								<span style="COLOR: #0000ff">="sessionFactory"</span>
								<span style="COLOR: #ff0000"> ref</span>
								<span style="COLOR: #0000ff">="sessionFactory"</span>
								<span style="COLOR: #0000ff">/&gt;</span>
						</font>
				</font>
				<span style="COLOR: #000000">
						<br />
						<font face="Courier New" size="2">    </font>
				</span>
				<font face="Courier New">
						<font size="2">
								<span style="COLOR: #0000ff">&lt;/</span>
								<span style="COLOR: #800000">bean</span>
								<span style="COLOR: #0000ff">&gt;</span>
						</font>
				</font>
				<span style="COLOR: #000000">
						<br />
						<br />
						<font face="Courier New" size="2">    </font>
				</span>
				<font face="Courier New">
						<font size="2">
								<span style="COLOR: #0000ff">&lt;</span>
								<span style="COLOR: #800000">bean </span>
								<span style="COLOR: #ff0000">id</span>
								<span style="COLOR: #0000ff">="urlMapping"</span>
								<span style="COLOR: #ff0000"> class</span>
								<span style="COLOR: #0000ff">="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"</span>
								<span style="COLOR: #0000ff">&gt;</span>
						</font>
				</font>
				<span style="COLOR: #000000">
						<br />
						<font face="Courier New" size="2">        </font>
				</span>
				<font face="Courier New">
						<font size="2">
								<span style="COLOR: #0000ff">&lt;</span>
								<span style="COLOR: #800000">property </span>
								<span style="COLOR: #ff0000">name</span>
								<span style="COLOR: #0000ff">="interceptors"</span>
								<span style="COLOR: #ff0000"> ref</span>
								<span style="COLOR: #0000ff">="openSessionInViewInterceptor"</span>
								<span style="COLOR: #0000ff">/&gt;</span>
						</font>
				</font>
				<span style="COLOR: #000000">
						<br />
						<font face="Courier New" size="2">        </font>
				</span>
				<font face="Courier New">
						<font size="2">
								<span style="COLOR: #0000ff">&lt;</span>
								<span style="COLOR: #800000">property </span>
								<span style="COLOR: #ff0000">name</span>
								<span style="COLOR: #0000ff">="mappings"</span>
								<span style="COLOR: #0000ff">&gt;</span>
						</font>
				</font>
				<span style="COLOR: #000000">
						<br />
						<font face="Courier New" size="2">            </font>
				</span>
				<font face="Courier New">
						<font size="2">
								<span style="COLOR: #0000ff">&lt;</span>
								<span style="COLOR: #800000">props</span>
						</font>
				</font>
				<span style="COLOR: #0000ff">
						<font face="Courier New" size="2">&gt;<br /></font>
				</span>
				<font face="Courier New">
						<font size="2">
								<span style="COLOR: #000000">            ......<br />            </span>
								<span style="COLOR: #0000ff">&lt;/</span>
								<span style="COLOR: #800000">props</span>
								<span style="COLOR: #0000ff">&gt;</span>
						</font>
				</font>
				<span style="COLOR: #000000">
						<br />
						<font face="Courier New" size="2">        </font>
				</span>
				<font face="Courier New">
						<font size="2">
								<span style="COLOR: #0000ff">&lt;/</span>
								<span style="COLOR: #800000">property</span>
								<span style="COLOR: #0000ff">&gt;</span>
						</font>
				</font>
				<span style="COLOR: #000000">
						<br />
						<font face="Courier New" size="2">    </font>
				</span>
				<font face="Courier New">
						<font size="2">
								<span style="COLOR: #0000ff">&lt;/</span>
								<span style="COLOR: #800000">bean</span>
								<span style="COLOR: #0000ff">&gt;</span>
						</font>
				</font>
		</div>
		<font face="Courier New" size="2">2. Filter </font>
		<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
				<font face="Courier New">
						<font size="2">
								<span style="COLOR: #0000ff">&lt;</span>
								<span style="COLOR: #800000">web-app</span>
								<span style="COLOR: #0000ff">&gt;</span>
						</font>
				</font>
				<span style="COLOR: #000000">
						<br />
						<font face="Courier New" size="2"> <br /></font>
				</span>
				<font face="Courier New">
						<font size="2">
								<span style="COLOR: #0000ff">&lt;</span>
								<span style="COLOR: #800000">filter</span>
								<span style="COLOR: #0000ff">&gt;</span>
						</font>
				</font>
				<span style="COLOR: #000000">
						<br />
				</span>
				<font face="Courier New">
						<font size="2">
								<span style="COLOR: #0000ff">&lt;</span>
								<span style="COLOR: #800000">filter-name</span>
								<span style="COLOR: #0000ff">&gt;</span>
								<span style="COLOR: #000000">hibernateFilter</span>
								<span style="COLOR: #0000ff">&lt;/</span>
								<span style="COLOR: #800000">filter-name</span>
								<span style="COLOR: #0000ff">&gt;</span>
						</font>
				</font>
				<span style="COLOR: #000000">
						<br />
				</span>
				<font face="Courier New">
						<font size="2">
								<span style="COLOR: #0000ff">&lt;</span>
								<span style="COLOR: #800000">filter-class</span>
								<span style="COLOR: #0000ff">&gt;</span>
						</font>
				</font>
				<span style="COLOR: #000000">
						<br />
						<font face="Courier New" size="2">org.springframework.orm.hibernate.support.OpenSessionInViewFilter<br /></font>
				</span>
				<font face="Courier New">
						<font size="2">
								<span style="COLOR: #0000ff">&lt;/</span>
								<span style="COLOR: #800000">filter-class</span>
								<span style="COLOR: #0000ff">&gt;</span>
						</font>
				</font>
				<span style="COLOR: #000000">
						<br />
				</span>
				<font face="Courier New">
						<font size="2">
								<span style="COLOR: #0000ff">&lt;/</span>
								<span style="COLOR: #800000">filter</span>
								<span style="COLOR: #0000ff">&gt;</span>
						</font>
				</font>
				<span style="COLOR: #000000">
						<br />
						<font face="Courier New" size="2"> <br /></font>
				</span>
				<font face="Courier New">
						<font size="2">
								<span style="COLOR: #0000ff">&lt;</span>
								<span style="COLOR: #800000">filter-mapping</span>
								<span style="COLOR: #0000ff">&gt;</span>
						</font>
				</font>
				<span style="COLOR: #000000">
						<br />
				</span>
				<font face="Courier New">
						<font size="2">
								<span style="COLOR: #0000ff">&lt;</span>
								<span style="COLOR: #800000">filter-name</span>
								<span style="COLOR: #0000ff">&gt;</span>
								<span style="COLOR: #000000">hibernateFilter</span>
								<span style="COLOR: #0000ff">&lt;/</span>
								<span style="COLOR: #800000">filter-name</span>
								<span style="COLOR: #0000ff">&gt;</span>
						</font>
				</font>
				<span style="COLOR: #000000">
						<br />
				</span>
				<font face="Courier New">
						<font size="2">
								<span style="COLOR: #0000ff">&lt;</span>
								<span style="COLOR: #800000">url-pattern</span>
								<span style="COLOR: #0000ff">&gt;</span>
								<span style="COLOR: #000000">*.do</span>
								<span style="COLOR: #0000ff">&lt;/</span>
								<span style="COLOR: #800000">url-pattern</span>
								<span style="COLOR: #0000ff">&gt;</span>
						</font>
				</font>
				<span style="COLOR: #000000">
						<br />
				</span>
				<font face="Courier New">
						<font size="2">
								<span style="COLOR: #0000ff">&lt;/</span>
								<span style="COLOR: #800000">filter-mapping</span>
								<span style="COLOR: #0000ff">&gt;</span>
						</font>
				</font>
				<span style="COLOR: #000000">
						<br />
						<br />
				</span>
				<font face="Courier New">
						<font size="2">
								<span style="COLOR: #0000ff">&lt;/</span>
								<span style="COLOR: #800000">web-app</span>
								<span style="COLOR: #0000ff">&gt;</span>
						</font>
				</font>
		</div>
		<br />
		<font face="Courier New" size="2">说明： 个人更喜欢用Interceptor方式， filter是在web.xml中定义<br />有了OpenSessionInView，并不是一切就ok了。简单的crud可以，但对于复杂业务逻辑就要想点法子。<br /><br />OSIV默认是request per session的, 所以即使没有显式update(po)，Hibernate也会帮你保存的，dao的业务判断就无效，还好有evict()可用。<br />update code </font>
		<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
				<font face="Courier New">
						<font size="2">
								<span style="COLOR: #000000">// Controller<br /></span>
								<span style="COLOR: #0000ff">public</span>
						</font>
				</font>
				<font face="Courier New">
						<font size="2">
								<span style="COLOR: #000000"> ModelAndView update() {<br />    p </span>
								<span style="COLOR: #000000">=</span>
						</font>
				</font>
				<font face="Courier New">
						<font size="2">
								<span style="COLOR: #000000"> dao.getVo(id);<br />    bindObject(request);<br />    dao.update(p);<br />}<br /><br />// Dao<br /></span>
								<span style="COLOR: #0000ff">public</span>
						</font>
				</font>
				<font face="Courier New">
						<font size="2">
								<span style="COLOR: #000000"> Object getVo(id) {<br />    p </span>
								<span style="COLOR: #000000">=</span>
						</font>
				</font>
				<font face="Courier New">
						<font size="2">
								<span style="COLOR: #000000"> getHibernateTemplate().get(clazz, id);<br />    p.getChilds().size();<br />    getHibernateTemplate().evict(p);<br />    </span>
								<span style="COLOR: #0000ff">return</span>
						</font>
				</font>
				<font face="Courier New">
						<font size="2">
								<span style="COLOR: #000000"> p;<br />}<br /><br /></span>
								<span style="COLOR: #0000ff">public</span>
								<span style="COLOR: #000000"> </span>
								<span style="COLOR: #0000ff">void</span>
						</font>
				</font>
				<font face="Courier New">
						<font size="2">
								<span style="COLOR: #000000"> update(p) {<br />    oldP </span>
								<span style="COLOR: #000000">=</span>
						</font>
				</font>
				<font face="Courier New">
						<font size="2">
								<span style="COLOR: #000000"> getVo(id);<br />    </span>
								<span style="COLOR: #008000">//</span>
								<span style="COLOR: #008000"> ++--(oldP);</span>
						</font>
				</font>
				<span style="COLOR: #008000">
						<br />
				</span>
				<font face="Courier New">
						<font size="2">
								<span style="COLOR: #000000">    getHibernateTemplate().update(p);<br />    </span>
								<span style="COLOR: #008000">//</span>
								<span style="COLOR: #008000"> ++--(p);</span>
						</font>
				</font>
				<span style="COLOR: #008000">
						<br />
				</span>
				<span style="COLOR: #000000">
						<font face="Courier New" size="2">}</font>
				</span>
		</div>
<img src ="http://www.blogjava.net/byterat/aggbug/94943.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/byterat/" target="_blank">比特鼠</a> 2007-01-19 15:33 <a href="http://www.blogjava.net/byterat/archive/2007/01/19/94943.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate 关键字key的自动生成</title><link>http://www.blogjava.net/byterat/archive/2007/01/18/94582.html</link><dc:creator>比特鼠</dc:creator><author>比特鼠</author><pubDate>Thu, 18 Jan 2007 02:44:00 GMT</pubDate><guid>http://www.blogjava.net/byterat/archive/2007/01/18/94582.html</guid><wfw:comment>http://www.blogjava.net/byterat/comments/94582.html</wfw:comment><comments>http://www.blogjava.net/byterat/archive/2007/01/18/94582.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/byterat/comments/commentRss/94582.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/byterat/services/trackbacks/94582.html</trackback:ping><description><![CDATA[
		<font face="Courier New" size="2">例如：<br />&lt;class name="User" table="user"&gt;<br />&lt;id name="id" column="id" type="java.lang.Long"&gt;<br /></font>
		<font face="Courier New">
				<font size="2">
						<font color="#ff0000">&lt;generator class="native"/&gt;<br /></font>&lt;/id&gt;<br /><br /><font color="#ff0000">generator</font>标识符生成器 描述<br /><br />increment　　　   适用于代理主键。由Hibernate自动以递增方式生成<br />identity　　　　  适用于代理主键。由底层数据库生成标识符<br />sequence　　　　  适用于代理主键。Hibernate根据底层数据库的序列生成标识符，这要求底层数据库支持序列<br />hilo　　　　　　   适用于代理主键。Hibernate分局high/low算法生成标识符<br />seqhilo　　　　　  适用于代理主键。使用一个高/低位算法来高效的生成long，short或者int类型的标识符。<br />native　　　　　   适用于代理主键。根据底层数据库对自动生成标识符的方式，自动选择identity、sequence或hilo<br />uuid.hex　　　　   适用于代理主键。Hibernate基于128 位UUID 算法生成16 进制数值（编码后以长度32 的字符串表示）<br />uuid.string　　    适用于代理主键。与uuid.hex 类似，只是生成的主键未进行编码（以长度16 的字符串表示），不能应用在 PostgreSQL 数据库中<br />assigned　　　　   适用于自然主键。由Java应用程序负责生成标识符<br />foreign　　　　　   适用于代理主键。使用另外一个相关联的对象的标识符<br /><br /></font>
		</font>
		<p>
				<font face="Courier New" size="2">以下举例：<br />1、指定参数的情况：<br />    &lt;id name="id" unsaved-value="0"&gt; <br />      &lt;generator class="sequence"&gt;<br />        &lt;param name="sequence"&gt;SEQ_CHILD&lt;/param&gt;<br />      &lt;/generator&gt;<br />&lt;/id&gt;<br />使用的是sequence，适合oracle数据库；</font>
		</p>
		<br />
		<p>
				<font face="Courier New" size="2">2、对于sql server2000中的数据库子增字段,在配置文件使用下列方法实现：<br />&lt;id name="id" type="long" unsaved-value="0"&gt;<br />     &lt;column name="id" sql-type="numeric" not-null="true" /&gt;<br />     &lt;generator class="identity" /&gt; <br />&lt;/id&gt;<br />这里主要是:identity:代表由sql server2000数据库自己提供子增字段.如果要hibernate自己提供,则用increment关键字来实现</font>
		</p>
		<br />
		<p>
				<font face="Courier New" size="2">3、如果表中的主键用字符串类型:可以用hibernate自己提供的方法实现主键唯一:<br />  &lt;id name="id" type="string" unsaved-value="null"&gt;<br />      &lt;column name="cid" sql-type="char(32)" not-null="true" /&gt;<br />      &lt;generator class="uuid.hex" /&gt;<br />  &lt;/id&gt;<br />使用的是uuid.hex: 采用128位的算法来生成一个32位字符串。最通用的一种方式。适用于所有数据库。</font>
		</p>
		<br />
		<p>
				<font face="Courier New" size="2">重要的知识点:<br />1. 如果有部门表,有员工表,员工表中有dep_id,则表部门类和员工类是one-to-many的关系:<br />   可以使用:  ( 在部门类department中使用下列)<br />   Department类:  <br />     /**  部门的所有员工   */<br />    private Set staffs = new TreeSet();<br />    <br />    xml的文件:<br />      &lt;set name="staffs" &gt;<br />          &lt;key column="dep_id"/&gt;<br />          &lt;one-to-many class="hbp.sys.data.Staff"/&gt;<br />      &lt;/set&gt;<br />      如果是list,需要用索引&lt;index&gt; &lt;/index&gt;,具体其中的含义,不是很明白.待以后研究<br />      <br /> 2. 如果部门要有一个负责人,即部门表(tb_department)中有一个字段:staff_id.<br />     那么表示部门和负责人之间的关系是many-to-one的关系<br />     Department类: <br />      /** 部门负责人id */<br />    private Staff staff;<br />    <br />    xml 文件<br />     &lt;many-to-one name="staff" class="hbp.sys.data.Staff"  column="staff_id"/&gt;  <br />  <br /> 3. 多对多关系,一般我们是做一个中间关联表.我用角色和权限做了个例子,<br />      Right(id,name)     Role(id,name)   中间表:tb_role_right(role_id,right_id)<br />      Right类中有一个Role的集合:private Set roles=new TreeSet();<br />      Role类中也有一个Right的集合:private Set rights=new TreeSet();<br />      则两者是明显的多对多关系.使用many-to-many来实现;<br />      xml文件中<br />      right.hbm.xml:如下:<br />        &lt;set name="roles" table="tb_role_right" cascade="all"&gt;<br />           &lt;key column="right_id"/&gt;<br />           &lt;many-to-many column="role_id" class="hbp.sys.data.Role"/&gt;<br />        &lt;/set&gt; <br />      role.hbm.xml文件中类似:<br />        &lt;set name="rights" table="tb_role_right" cascade="all"&gt;<br />          &lt;key column="role_id"/&gt;<br />          &lt;many-to-many column="right_id" class="hbp.sys.data.Right"/&gt;<br />        &lt;/set&gt; </font>
		</p>
		<br />
		<p>
				<font face="Courier New" size="2">4. 几个值得注意的问题:<br />        a)在xml?映射文件中,写类的名字时一定用类的全名:即:包+类名如:(hbp.sys.data.Staff),这个错误使我费了半天劲.:(<br />        b)我在写实现基本DAO操作时,写了<br />             session.delete("from Right as right where right.id="+id);  <br />             程序死活报错,我折腾了半天,跟踪到底,才恍然大悟,hibernate在解析sql语句的时候把<br />             其中的right,当成了数据库中的右连接("保留字"),唉,这种关键字,不能随便用啊,:)</font>
		</p>
		<br />
		<p>
				<font face="Courier New" size="2">5. hibernate中HQL语言的查询根据你的sql的不同而返回不同的对象类型.<br />         如果你使用session.find(String hql)<br />         一般会返回一个List,如:from Staff staff;返回的是包含所有的员工对象的集合<br />         如你的hql为:select count(*) from Staff staff;则返回的是一个Integer对象<br />         如果你使用的hql为:select count(distinct staff.name),count(*) from Staff staff;则返回的是一个Object<br />         即Object[],需要先把他转换成Object[],然后在取[0],[1].<br />         这种设计我不知道hibernate是如何处理的,感觉既好也不好.好的是可以使用一个find获得任意查询<br />         不好在于根据hql来处理返回结果,容易出错.</font>
		</p>
<img src ="http://www.blogjava.net/byterat/aggbug/94582.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/byterat/" target="_blank">比特鼠</a> 2007-01-18 10:44 <a href="http://www.blogjava.net/byterat/archive/2007/01/18/94582.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>