spring的事务解读

来源:互联网 发布:pes2017曼城数据 编辑:程序博客网 时间:2024/05/22 06:57

spring整合hibernate,事务的管控全部由spring容器来处理

     这里简单的讲解下事务的管控

   配置文件:

<!-- 事务管理器 --> <bean id="transactionManager"  class="org.springframework.orm.hibernate4.HibernateTransactionManager">          <property name="sessionFactory" ref="sessionFactory"></property>      </bean>          <!-- 通知,引入事务管理器 -->     <tx:advice id="txAdvice" transaction-manager="transactionManager">          <tx:attributes>           <!-- 指定哪些方法需要加入事务,这里懒惰一下全部加入,可以使用通配符来只加入需要的方法 -->           <!--              事务的传播行为介绍:                propagation=Propagation.REQUIRED                   如果有事务, 那么加入事务, 没有的话新建一个(默认情况下)                propagation=Propagation.NOT_SUPPORTED                   容器不为这个方法开启事务                propagation=Propagation.REQUIRES_NEW                   不管是否存在事务,都创建一个新的事务,原来的挂起,新的执行完毕,继续执行老的事务                propagation=Propagation.MANDATORY                  必须在一个已有的事务中执行,否则抛出异常                propagation=Propagation.NEVER                    必须在一个没有的事务中执行,否则抛出异常(与Propagation.MANDATORY相反)                propagation=Propagation.SUPPORTS                   如果其他bean调用这个方法,在其他bean中声明事务,那就用事务.如果其他bean没有声明事务,那就不用事务          -->            <tx:method name="insert*" propagation="REQUIRED" />              <tx:method name="update*" propagation="REQUIRED" />              <tx:method name="delete*" propagation="REQUIRED" />              <tx:method name="get*" propagation="REQUIRED" read-only="true"/>              <tx:method name="query*" propagation="REQUIRED" read-only="true"/>              <tx:method name="*" propagation="REQUIRED" />          </tx:attributes>      </tx:advice>            <aop:config>          <!-- 切入点指明了在执行Service的所有方法时产生事务拦截操作 -->          <aop:pointcut id="daoMethods" expression="execution(* com.asiainfo.spring.dao.impl.*.*(..))" />              <!-- 定义了将采用何种拦截操作,这里引用到 txAdvice -->          <aop:advisor advice-ref="txAdvice" pointcut-ref="daoMethods" />      </aop:config>    
这里特别要注意的,就是获取session的方式,我们之前是sessionFactory.openSession方式来获取Session,但是我们配置了事务管理器以后,对数据无法做持久层操作,

  我们可以翻翻源码HibernateTransactionManager,因为我们的sessionFactory交给事务管理器以后,获取的方式就不一样了。

@SuppressWarnings("serial")public class HibernateTransactionManager extends AbstractPlatformTransactionManagerimplements ResourceTransactionManager, BeanFactoryAware, InitializingBean {private SessionFactory sessionFactory;private DataSource dataSource;private boolean autodetectDataSource = true;private boolean prepareConnection = true;private boolean hibernateManagedSession = false;private Object entityInterceptor;

里面有一个方法:

  

@Overrideprotected Object doGetTransaction() {HibernateTransactionObject txObject = new HibernateTransactionObject();txObject.setSavepointAllowed(isNestedTransactionAllowed());SessionHolder sessionHolder =(SessionHolder) TransactionSynchronizationManager.getResource(getSessionFactory());if (sessionHolder != null) {if (logger.isDebugEnabled()) {logger.debug("Found thread-bound Session [" + sessionHolder.getSession() + "] for Hibernate transaction");}txObject.setSessionHolder(sessionHolder);}else if (this.hibernateManagedSession) {try {Session session = this.sessionFactory.getCurrentSession();if (logger.isDebugEnabled()) {logger.debug("Found Hibernate-managed Session [" + session + "] for Spring-managed transaction");}txObject.setExistingSession(session);}catch (HibernateException ex) {throw new DataAccessResourceFailureException("Could not obtain Hibernate-managed Session for Spring-managed transaction", ex);}}if (getDataSource() != null) {ConnectionHolder conHolder = (ConnectionHolder)TransactionSynchronizationManager.getResource(getDataSource());txObject.setConnectionHolder(conHolder);}return txObject;}

观察可以发现Session session = this.sessionFactory.getCurrentSession();  我们需要以这种方式才能做事务的控制处理,才能做持久层操作!
package com.asiainfo.spring.dao.impl;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.springframework.beans.factory.annotation.Autowired;public class BaseDao {@Autowired    private SessionFactory sessionFactory;public SessionFactory getSessionFactory() {return sessionFactory;}public void setSessionFactory(SessionFactory sessionFactory) {this.sessionFactory = sessionFactory;}public Session getSession(){return sessionFactory.getCurrentSession();}    }
这样才能处理成功

  测试: 

package com.asiainfo.spring.test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import com.asiainfo.spring.dao.interfaces.IProvAndCityDao;import com.asiainfo.spring.pojo.City;import com.asiainfo.spring.pojo.Province;public class SpringHibernateTest {public static void main(String[] args) {      ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");            IProvAndCityDao HelloBean = (IProvAndCityDao)ac.getBean("IProvAndCityDao");            /*List<City> list = HelloBean.queryAllCityInfo();                for(City city :list){        System.out.println(city.getName()+"..."+city.getPro().getName());        }*/                City city = new City();                city.setId(392);                city.setName("曾孟良");        Province pro = new Province();                pro.setId(35);                pro.setName("台湾");                city.setPro(pro);                HelloBean.insertCityInfo(city);         }}
结果:

    

     

0 0