<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>温水青蛙的池塘</title>
    <description></description>
    <link>http://bloodwolf-china.javaeye.com</link>
    <language>UTF-8</language>
    <copyright>Copyright 2003-2008, JavaEye.com</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>JavaEye - 做最棒的软件开发交流社区</generator>
      <item>
        <title>使用Spring的Log4jConfigListener注意修改webAppKey</title>
        <author>bloodwolf_china</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://bloodwolf-china.javaeye.com">bloodwolf_china</a>&nbsp;
          链接：<a href="http://bloodwolf-china.javaeye.com/blog/227552" style="color:red;">http://bloodwolf-china.javaeye.com/blog/227552</a>&nbsp;
          发表时间: 2008年08月13日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          　　在使用spring先后开发了两个模块，单独测试都正常。也先后上线运行，之后发现有个模块在启动Tomcat后总是初始化失败，必须到tomcat管理控制台手动启动。找了半天也没发现原因。后来管理员在每次重启Tomcat后这个模块没有运行导致一堆问题和麻烦，今天特意查看了其他的tomcat日志文件，终于发现了问题所在，原来是Log4jConfigListener。使用它是为了随时调整打印日志的级别而不用重启服务。没想到没有享受到它的便利，反而出了一堆问题，只能怪自己没有稍微仔细研究一下。<br />web.xml<br /><pre name="code" class="xml">
&lt;context-param>
	&lt;param-name>webAppRootKey&lt;/param-name>
		&lt;param-value>message.web.root&lt;/param-value>
	&lt;/context-param>

	&lt;context-param>
		&lt;param-name>log4jConfigLocation&lt;/param-name>
		&lt;param-value>/WEB-INF/classes/log4j.properties&lt;/param-value>
	&lt;/context-param>

	&lt;context-param>
		&lt;param-name>log4jRefreshInterval&lt;/param-name>
		&lt;param-value>60000&lt;/param-value>
	&lt;/context-param>
	&lt;listener>
		&lt;listener-class>org.springframework.web.util.Log4jConfigListener&lt;/listener-class>
	&lt;/listener>
</pre><br />log4j.properties配置<br /><pre name="code" class="java">
layoutPattern=[%d{HH:mm:ss}] %-5p : %m%n
log.file=${message.web.root}/logs/app.log

log4j.appender.logfile=org.apache.log4j.DailyRollingFileAppender
log4j.appender.logfile.File=${log.file}
log4j.appender.logfile.Append=true
log4j.appender.logfile.DatePattern='.'yyyyMMdd
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=${layoutPattern}
</pre><br />其实需要注意的地方就是应用服务器下有不止一个的应用在使用spring的Log4jConfigListener需要修改web环境中webAppRootKey值(这个值其实是web应用的根目录在环境变量名，这样在log4j配置文件中如果有相对web目录的路径就不用写死了)。<br />否则两个默认值web.root在环境变量中就会有冲突导致第二个应用启动失败。
          <br/>
          <span style="color:red;">
            <a href="http://bloodwolf-china.javaeye.com/blog/227552#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 13 Aug 2008 15:11:22 +0800</pubDate>
        <link>http://bloodwolf-china.javaeye.com/blog/227552</link>
        <guid>http://bloodwolf-china.javaeye.com/blog/227552</guid>
      </item>
      <item>
        <title>JMS Apache ActiveMQ使用(3)</title>
        <author>bloodwolf_china</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://bloodwolf-china.javaeye.com">bloodwolf_china</a>&nbsp;
          链接：<a href="http://bloodwolf-china.javaeye.com/blog/208297" style="color:red;">http://bloodwolf-china.javaeye.com/blog/208297</a>&nbsp;
          发表时间: 2008年06月26日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <img src="/images/smiles/icon_smile.gif"/>还有工作就是如何接受JMS Message并进行处理了，spring中也有现成的框架进行处理MessageListenerAdapter和DefaultMessageListenerContainer，我们只要写一个普通类编写处理消息的逻辑，具体如何接收消息都由Spring完成。<br />spring-listener-jms.xml<br /><pre name="code" class="xml">
&lt;?xml version="1.0" encoding="GBK"?>
&lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN"
		"http://www.springframework.org/dtd/spring-beans-2.0.dtd">
&lt;beans>
	&lt;import resource="spring-jms.xml"/>

	&lt;bean id="messageListener" class="org.springframework.jms.listener.adapter.MessageListenerAdapter">
		&lt;constructor-arg>
			&lt;bean class="com.viva.server.message.jms.UserRegisterListener"/>
		&lt;/constructor-arg>
		&lt;property name="defaultListenerMethod" value="onRegister"/>
		&lt;property name="messageConverter" ref="messageConvert"/>
	&lt;/bean>

	&lt;bean id="queueListenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
		&lt;property name="connectionFactory" ref="jmsFactory"/>
		&lt;property name="destination" ref="queueDestination"/>
		&lt;property name="messageListener" ref="messageListener"/>
	&lt;/bean>

	&lt;bean id="topicListenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
		&lt;property name="connectionFactory" ref="jmsFactory"/>
		&lt;property name="destination" ref="topicDestination"/>
		&lt;property name="messageListener" ref="messageListener"/>
	&lt;/bean>

&lt;/beans>
</pre><br /><img src="/images/smiles/icon_smile.gif"/>从配置文件可以看出配置了一个Topic监听器和Queue监听器，实际的监听类就是一个UserRegisterListener，由它处理用户注册事件。<br />UserRegisterListener.java代码<br /><pre name="code" class="java">
public class UserRegisterListener {
	public void onRegister(VivaUserRegisterMessage registerMessage){
		System.out.println("User Register,tel="+ registerMessage.getTel()+ ",time="+registerMessage.getRegisterTime());	
	}
}
</pre><br /><img src="/images/smiles/icon_smile.gif"/>最后写一个JUnit测试用户来测试一下代码<br />JMSTestor.java<br /><pre name="code" class="java">
public class JMSTestor extends TestCase {
	private ApplicationContext context;

	public void testQueueSend(){
		context = new ClassPathXmlApplicationContext("spring-jms.xml");
		JmsTemplate jmsTemplate = (JmsTemplate) context.getBean("queueTemplate");
		VivaUserRegisterMessage msg = new VivaUserRegisterMessage();
		msg.setRegisterTime(new Date());
		msg.setTel("1385199XXXX");
		msg.setUserId(1);
		jmsTemplate.convertAndSend(msg);
	}

	public void testTopicSend(){
		context = new ClassPathXmlApplicationContext("spring-jms.xml");
		JmsTemplate jmsTemplate = (JmsTemplate) context.getBean("topicTemplate");
		VivaUserRegisterMessage msg = new VivaUserRegisterMessage();
		msg.setRegisterTime(new Date());
		msg.setTel("1385199XXXX");
		msg.setUserId(1);
		jmsTemplate.convertAndSend(msg);
	}

	public void testListener()throws Exception{
		context = new ClassPathXmlApplicationContext("spring-listener-jms.xml");
		Thread.sleep(1000*60*30);
	}

	
}
</pre><br />执行testTopicSend发送JMS Message到Topic<br />执行testQueueSend发送JMS Message到Queue<br />执行testListener启动Topic和Queue监听器处理JMS Message<br /><img src="/images/smiles/icon_smile.gif"/>完成！另外ActiveMQ集成了Jetty服务，可以访问地址http://localhost:8161/admin/查看具体信息
          <br/>
          <span style="color:red;">
            <a href="http://bloodwolf-china.javaeye.com/blog/208297#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 26 Jun 2008 17:11:10 +0800</pubDate>
        <link>http://bloodwolf-china.javaeye.com/blog/208297</link>
        <guid>http://bloodwolf-china.javaeye.com/blog/208297</guid>
      </item>
      <item>
        <title>JMS Apache ActiveMQ使用(1)</title>
        <author>bloodwolf_china</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://bloodwolf-china.javaeye.com">bloodwolf_china</a>&nbsp;
          链接：<a href="http://bloodwolf-china.javaeye.com/blog/208291" style="color:red;">http://bloodwolf-china.javaeye.com/blog/208291</a>&nbsp;
          发表时间: 2008年06月26日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <img src="/images/smiles/icon_smile.gif"/>现在的系统业务是每人开发一个模块，然后用HTTP接口访问。由多个用个用户注册的入口，用户注册事件处理也分布到不同的代码里。看起来相当不舒服，所以决定使用JMS来处理事件触发后的逻辑，降低系统的耦合，也方便开发修改代码。<br />     <img src="/images/smiles/icon_smile.gif"/>以前也只是听说过MQ，但一直也开发过这方面的程序，趁此机会正好学习一下。由于现在开发的也不是什么大型系统，采用Apache的ActiveMQ就足够了。网上很多资料都是把ActiveMQ嵌入到web模块中，就现在的系统而言由于业务模块会经常更新，这种方式会导致其他使用ActiveMQ的JMS Client发送消息失败。所以还是独立的ActiveMQ比较好。首先下载<a href="http://activemq.apache.org/" target="_blank">ActiveMQ</a>,我下载的是5.10版。解压缩到一个目录。修改conf/activemq.xml配置文件，把持久化方式改为数据库保存<br /><pre name="code" class="xml">
&lt;!--此处默认采用TCP Connector,端口61616,可以不用修改-->
&lt;transportConnectors>
            &lt;transportConnector name="openwire" uri="tcp://localhost:61616" discoveryUri="multicast://default"/>
&lt;/transportConnectors>

&lt;persistenceAdapter>
      &lt;jdbcPersistenceAdapter dataSource="#oracle-ds"/>
&lt;/persistenceAdapter>

&lt;bean id="oracle-ds" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
      &lt;property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
      &lt;property name="url" value="jdbc:oracle:thin:@192.168.1.10:1521:mysid"/>
      &lt;property name="username" value="huzl"/>
      &lt;property name="password" value="j7Z"/>
      &lt;property name="maxActive" value="200"/>
      &lt;property name="poolPreparedStatements" value="true"/>
    &lt;/bean>
</pre><br />具体详细的配置说明我也没找到，不过可以参照其<a href="http://activemq.apache.org/schema/core/activemq-core-5.1.0.xsd" target="_blank">/activemq-core-5.1.0.xsd</a>文件<br /><br />然后启动ActvieMQ服务(bin/activemq.bat)，服务器配置就到到这儿了。
          <br/>
          <span style="color:red;">
            <a href="http://bloodwolf-china.javaeye.com/blog/208291#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 26 Jun 2008 16:57:22 +0800</pubDate>
        <link>http://bloodwolf-china.javaeye.com/blog/208291</link>
        <guid>http://bloodwolf-china.javaeye.com/blog/208291</guid>
      </item>
      <item>
        <title>JMS Apache ActiveMQ使用(2)</title>
        <author>bloodwolf_china</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://bloodwolf-china.javaeye.com">bloodwolf_china</a>&nbsp;
          链接：<a href="http://bloodwolf-china.javaeye.com/blog/208290" style="color:red;">http://bloodwolf-china.javaeye.com/blog/208290</a>&nbsp;
          发表时间: 2008年06月26日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <img src="/images/smiles/icon_smile.gif"/>下面就进行程序开发，没得说，当然是spring了<br /><img src="/images/smiles/icon_smile.gif"/>使用spring开发JMS比较简单，直接使用的是JmsTemplate，需要几个相关对象。<br /><ul><br />ConnectionFactory：创建与ActiveMQ连接的工厂类<br />Destination：目标Topic或Queue<br />MessageConverter：在Java POJO和JMS Message进行转换<br /></ul><br />关于JMS的其他接口如Session，MessageProducer/MessageConsumer都是在JmsTemplate内部处理，不需要开发关注具体细节。<br />首先配置分别针对Topic和Queue的JmsTemplate(其实发送和接受消息代码中不需要关心是Topic还是Queue，JMS 1.1标准对于两者在客户端的处理已经可以通用了)<br /><br />spring-jms.xml<br /><pre name="code" class="xml">
&lt;?xml version="1.0" encoding="GBK"?>
&lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN"
		"http://www.springframework.org/dtd/spring-beans-2.0.dtd">
&lt;beans>
	&lt;bean id="jmsFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
		&lt;property name="brokerURL" value="failover:(tcp://localhost:61616)"/>
		&lt;property name="transportListener">
			&lt;bean class="com.viva.server.message.jms.JmsTransportListener"/>
		&lt;/property>
  &lt;/bean>

	&lt;bean id="queueDestination" class="org.apache.activemq.command.ActiveMQQueue">
		&lt;constructor-arg value="Huzl.queue">&lt;/constructor-arg>
	&lt;/bean>

	&lt;bean id="topicDestination" class="org.apache.activemq.command.ActiveMQTopic">
		&lt;constructor-arg value="Huzl.topic">&lt;/constructor-arg>
	&lt;/bean>

	&lt;bean id="messageConvert" class="com.viva.server.message.jms.VivaMessageConvert"/>

	&lt;bean id="queueTemplate" class="org.springframework.jms.core.JmsTemplate">
        &lt;property name="connectionFactory" ref="jmsFactory" />
		&lt;property name="defaultDestination" ref="queueDestination"/>
		&lt;property name="messageConverter" ref="messageConvert"/>
    &lt;/bean>

	&lt;bean id="topicTemplate" class="org.springframework.jms.core.JmsTemplate">
        &lt;property name="connectionFactory" ref="jmsFactory" />
		&lt;property name="defaultDestination" ref="topicDestination"/>
		&lt;property name="messageConverter" ref="messageConvert"/>
    &lt;/bean>
&lt;/beans>
</pre><br />VivaMessageConvert.java代码，使用的是JMS的MapMessage，而VivaUserRegisterMessage类是业务中用到的POJO，代码就不贴出来了。<br /><pre name="code" class="java">
import org.springframework.jms.support.converter.MessageConversionException;
import org.springframework.jms.support.converter.MessageConverter;

import javax.jms.JMSException;
import javax.jms.MapMessage;
import javax.jms.Message;
import javax.jms.Session;
import java.util.Date;

/**
 * User: bloodwolf_china
 * Date: 2008-6-24
 * Time: 15:20:42
 * Descript:
 */
public class VivaMessageConvert implements MessageConverter {
	public Message toMessage(Object object, Session session) throws JMSException, MessageConversionException {
		MapMessage msg = session.createMapMessage();
		VivaUserRegisterMessage registerMessage = (VivaUserRegisterMessage) object;
		msg.setLong("RegisterTime",registerMessage.getRegisterTime().getTime());
		msg.setInt("UserId",registerMessage.getUserId());
		msg.setString("Tel",registerMessage.getTel());
		return msg;  
	}

	public Object fromMessage(Message message) throws JMSException, MessageConversionException {
		MapMessage msg = (MapMessage) message;
		VivaUserRegisterMessage registerMessage = new VivaUserRegisterMessage();
		registerMessage.setRegisterTime(new Date(msg.getLong("RegisterTime")));
		registerMessage.setUserId(msg.getInt("UserId"));
		registerMessage.setTel(msg.getString("Tel"));
		return registerMessage;
	}
}
</pre><br />到这儿客户端发送消息的准备工作已经完成了，可以从spring取得queueTemplate/topicTemplat发送JMS Message了<br /><img src="/images/smiles/icon_smile.gif"/>注意其中brokerURL的值为"failover:(tcp://localhost:61616)",其中failover关键字表示客户端与ActiveMQ Server的连接中断后(如Server重新启动)，客户端会自动重新连接，不需要在我们的代码中处理了。但是有个麻烦就是使用JmsTemplate发送消息时，当前的线程也会被wait直到重新连接ActiveMQ服务器成功，这种情况可能会导致线程被耗尽的危险。所以可以配置一个TransportListener，在连接错误时把消息放入缓存队列中，连接成功后再发送。
          <br/>
          <span style="color:red;">
            <a href="http://bloodwolf-china.javaeye.com/blog/208290#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 26 Jun 2008 16:56:44 +0800</pubDate>
        <link>http://bloodwolf-china.javaeye.com/blog/208290</link>
        <guid>http://bloodwolf-china.javaeye.com/blog/208290</guid>
      </item>
      <item>
        <title>HibernateTemplate使用之手工管理Session和Transaction</title>
        <author>bloodwolf_china</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://bloodwolf-china.javaeye.com">bloodwolf_china</a>&nbsp;
          链接：<a href="http://bloodwolf-china.javaeye.com/blog/200160" style="color:red;">http://bloodwolf-china.javaeye.com/blog/200160</a>&nbsp;
          发表时间: 2008年06月04日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          大多数人在第一次使用HibernateTemplate时都很好奇，不需要自己关闭Hibernate Session。如果在需要使用事务的情况一般使用spring配置TransactionProxyFactoryBean用AOP方式实现，还有就是使用HibernateTemplate的execute(HibernateCallback action)方法，构造一个匿名类实现HibernateCallback接口的Object doInHibernate(Session session)方法。使用前一种方法需要使用spring IOC，后一种代码因为使用匿名类，如果有较多逻辑代码显得难看、不清晰。是否还有其他使用HibernateTemplate的简单方法呢。<br />	查看HibernateTemplate源码发现，如果不存在事务，每次执行HibernateTemplate方法都会取得新Session，执行完数据库操作后再关闭Session。虽说不是每次都是真正开关数据库连接，但总感觉这样做不好。我们需要即使多次执行HibernateTemplate中方法是用的同一个Session，这样既不浪费资源，也可以自己手工管理事务。现在就来写一个工具类模拟OpenSessionInView模式和HibernateTransactionManager功能<br /><pre name="code" class="java">
import org.hibernate.FlushMode;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.orm.hibernate3.SessionFactoryUtils;
import org.springframework.orm.hibernate3.SessionHolder;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.Assert;

public class HibernateSessionUtils{

	private static final ThreadLocal sessionFactoryLocal = new ThreadLocal();

	public static void getSession(SessionFactory sessionFactory){
		getSession(sessionFactory,null);
	}

	public static void getSession(SessionFactory sessionFactory,FlushMode flushMode){
		if (TransactionSynchronizationManager.hasResource(sessionFactory))return;
		Session session = SessionFactoryUtils.getSession(sessionFactory, true);
		if (flushMode != null) {
			session.setFlushMode(flushMode);
		}
		TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session));
		sessionFactoryLocal.set(sessionFactory);
	}

	public static void beginTransaction(){
		SessionFactory sessionFactory = (SessionFactory) sessionFactoryLocal.get();
		Assert.state(sessionFactory != null,"No existing sessionFactory found for thread");
		SessionHolder sessionHolder = (SessionHolder)TransactionSynchronizationManager.getResource(sessionFactory);
		Assert.state(sessionHolder != null,"No existing session found for transaction");
		Transaction transaction = sessionHolder.getTransaction();
		Assert.state(transaction == null,"transaction already found for transaction");
		transaction = sessionHolder.getSession().beginTransaction();
		transaction.begin();
		sessionHolder.setTransaction(transaction);
	}
	
	public static void commit(){
		commit(true);
	}
	public static void commit(boolean autoClose){
		SessionFactory sessionFactory = (SessionFactory) sessionFactoryLocal.get();
		Assert.state(sessionFactory != null,"No existing sessionFactory found for thread");
	    SessionHolder sessionHolder = (SessionHolder)TransactionSynchronizationManager.getResource(sessionFactory);
		Assert.state(sessionHolder != null,"No existing session found for transaction");
		Transaction transaction = sessionHolder.getTransaction();
		Assert.state(transaction != null,"No transaction found for transaction");
		transaction.commit();
		sessionHolder.setTransaction(null);
		if(autoClose)
			closeSession();
	}

	public static void rollback(){
		SessionFactory sessionFactory = (SessionFactory) sessionFactoryLocal.get();
		Assert.state(sessionFactory != null,"No existing sessionFactory found for thread");
		SessionHolder sessionHolder = (SessionHolder)TransactionSynchronizationManager.getResource(sessionFactory);
		Assert.state(sessionHolder != null,"No existing session found for transaction");
		Transaction transaction = sessionHolder.getTransaction();
		Assert.state(transaction != null,"No transaction found for transaction");
		transaction.rollback();
		sessionHolder.setTransaction(null);
	}

	public static void closeSession(){
		SessionFactory sessionFactory = (SessionFactory) sessionFactoryLocal.get();
		if(sessionFactory == null)return;
		SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.unbindResource(sessionFactory);
		if(sessionHolder != null){
			Transaction transaction = sessionHolder.getTransaction();
			Assert.state(transaction == null,"Transaction found for session");
		}
		SessionFactoryUtils.closeSession(sessionHolder.getSession());
		sessionFactoryLocal.set(null);
	}

}

</pre><br /><br />使用示例<br /><pre name="code" class="java">
public static void main(String[] args) {
		SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
		HibernateTemplate template = new HibernateTemplate(sessionFactory);
		HibernateSessionUtils.getSession(sessionFactory);
		//do any thing
		template.find("....");
		HibernateSessionUtils.beginTransaction();
		template.save(null);
		HibernateSessionUtils.commit();
		HibernateSessionUtils.closeSession();
	}
</pre><br />编写测试代码或少量代码可以采用这种方式，如果是真正应用的话还是使用Spring IOC和AOP比较好，不推荐这种手工方式
          <br/>
          <span style="color:red;">
            <a href="http://bloodwolf-china.javaeye.com/blog/200160#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 04 Jun 2008 16:57:15 +0800</pubDate>
        <link>http://bloodwolf-china.javaeye.com/blog/200160</link>
        <guid>http://bloodwolf-china.javaeye.com/blog/200160</guid>
      </item>
  </channel>
</rss>