Spring对Hibernate的事务管理

上一篇文章我们进行了基本的框架搭建,实现了登录和全查功能。这都属于查询操作,如果要进行增删改等需要对数据库修改的操作时就需要进行事务操作。
我们在执行增删改操作的时候在方法中使用session缓存手动开启事务,等执行完持久化操作之后在进行事务的提交。这就是编程式事务,但是每个方法都进行一个事务的开启,提交,回滚等操作的话太过麻烦。
我们现在是SSH框架的整合,由Spring对Hibernate和Struts2进行管理,Spring可以拥有全部的控制权,其中就包括事务,Spring的Aop提供了对事务的支持,只需要在Spring配置文件中声明事务就可以实现对事务的统一管理,并且不需要再在DAO层的方法中手动的开启事务,能简化对数据的持久化操作。这是声明式事务。

方法一:声明式事务的配置:

继续使用上一片文章中搭建项目,打开applicationContext.xml,声明式事务的配置就需要增加applicationContext.xml的命名空间,tx和aop的命名空间,下面是增加命名空间后的头部信息

	<beans xmlns="http://www.springframework.org/schema/beans"
		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		xmlns:context="http://www.springframework.org/schema/context"
		xmlns:aop="http://www.springframework.org/schema/aop"
		xmlns:tx="http://www.springframework.org/schema/tx"
		xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
			http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
			http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
			http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd">

首先需要配置Hibernate事务管理器bean,并注入sessionFactory属性

	<bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
		<property name="sessionFactory" ref="sessionFactory">property>
	bean>

这样就可以使用Spring管理Hibernate的事务,然后配置事务增强,就是配置事务的规则,指定那些方法执行事务和执行事务的规则

	
	
	<tx:advice id="txAdvice" transaction-manager="transactionManager">
		
		<tx:attributes>
			
			<tx:method name="query*" read-only="true" propagation="REQUIRED"/>
			<tx:method name="*Update" read-only="false" propagation="REQUIRES_NEW" />
			<tx:method name="*" propagation="REQUIRED"/>
		tx:attributes>
	tx:advice>

然后定义事务的切入点,事务的切入点使用execution表达式进行描述,表达式描述事务的切入点方法所在类的全路径,因为service层有可能执行多个dao层的方法,所以我们这里定义service层的所有方法

	
	<aop:config proxy-target-class="true">
		
		<aop:pointcut expression="execution(* org.hua.service.*.*(..))" id="pointcut"/>
		
		<aop:advisor advice-ref="txAdvice" pointcut="pointcut"/>
	aop:config>

注意如果事务切入的类实现了至少一个接口那么就会出现
org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type
或者Java.lang.ClassCastException: 异常,有两个解决办法

  • 1:就是设置proxy-target-class="true"这个属性,proxy-target-class="true"这个属性一定要设置为true(默认false),这个属性是指定基于接口还是类的代理被创建,如果不设置默认为false
  • 2:Spring Ioc容器中放入的是哪个接口的实现类就声明那个接口接收

execution表达式常见举例
Spring对Hibernate的事务管理_第1张图片

自此就完成Spring的声明式事务的配置

方法二:使用@Transactional实现注解事务管理

spring配置文件头部信息跟上边一样
同样配置事务管理器,然后开启注解事务

	
	<bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
		<property name="sessionFactory" ref="sessionFactory">property>
	bean>
	
	<tx:annotation-driven transaction-manager="transactionManager"/>

然后在需要开启事务的类或方法上边直接加上@Transactional即可
事务规则可以在注解里面进行配置,具体规则参照上面

	@Transactional(readOnly=true,rollbackFor=Exception.class,propagation=Propagation.REQUIRED)
	public void empDel(int id) {
		
		edi.empDel(id);
		
	}

Spring提供的@Transaction注解事务管理,内部同样是利用环绕通知TransactionInterceptor实现事务的开启及关闭。
使用@Transactional注意点:

  • 如果在接口、实现类或方法上都指定了@Transactional 注解,则优先级顺序为方法>实现类>接口;
  • 建议只在实现类或实现类的方法上使用@Transactional,而不要在接口上使用,这是因为如果使用JDK代理机制(基于接口的代理)是没问题;而使用使用CGLIB代理(继承)机制时就会遇到问题,因为其使用基于类的代理而不是接口,这是因为接口上的@Transactional注解是“不能继承的”

你可能感兴趣的:(Spring对Hibernate的事务管理)