Spring 专题
专题目录
您的位置:java > Spring专题 > Spring AOP在Hibernate事务管理
Spring AOP在Hibernate事务管理
作者:--    发布时间:2019-11-20
事务管理是用来以确保数据库中数据的完整性和一致性。spring aop技术允许开发者管理事务的声明。
这里有一个例子来说明如何使用spring aop 来管理 hibernate 事务。整个工程的文件结构如下所示:

p.s 这里很多hibernate和spring配置文件是隐藏的,只有一些重要的文件显示,如果你想看全部文件,请在文章的结尾下载完整的项目代码。

1.创建表

mysql表的脚本,一个“product”表
create table  `h3`.`product` (
  `product_id` bigint(20) unsigned not null auto_increment,
  `product_code` varchar(20) not null,
  `product_desc` varchar(255) not null,
  primary key (`product_id`) using btree
) engine=innodb auto_increment=1 default charset=utf8;

create table  `h3`.`product_qoh` (
  `qoh_id` bigint(20) unsigned not null auto_increment,
  `product_id` bigint(20) unsigned not null,
  `qty` int(10) unsigned not null,
  primary key (`qoh_id`),
  key `fk_product_qoh_product_id` (`product_id`),
  constraint `fk_product_qoh_product_id` foreign key (`product_id`) 
  references `product` (`product_id`)
) engine=innodb auto_increment=1 default charset=utf8;

2.产品业务对象

在这个“productbo”实现save()方法将插入记录到“product“通过“productdao”,并通过“productqohbo”类库存量到“productqoh'表。
package com.h3.product.bo.impl;

import com.h3.product.bo.productbo;
import com.h3.product.bo.productqohbo;
import com.h3.product.dao.productdao;
import com.h3.product.model.product;
import com.h3.product.model.productqoh;

public class productboimpl implements productbo{
	
	productdao productdao;
	productqohbo productqohbo;
	
	public void setproductdao(productdao productdao) {
		this.productdao = productdao;
	}
	
	public void setproductqohbo(productqohbo productqohbo) {
		this.productqohbo = productqohbo;
	}

	//this method need to be transactional
	public void save(product product, int qoh){
		
		productdao.save(product);
		system.out.println("product inserted");
		
		productqoh productqoh = new productqoh();
		productqoh.setproductid(product.getproductid());
		productqoh.setqty(qoh);
		
		productqohbo.save(productqoh);
		system.out.println("productqoh inserted");
	}
}
spring 的 bean 配置文件。
<!-- product business object -->
   <bean id="productbo" class="com.h3.product.bo.impl.productboimpl" >
   	<property name="productdao" ref="productdao" />
   	<property name="productqohbo" ref="productqohbo" />
   </bean>
 
   <!-- product data access object -->
   <bean id="productdao" class="com.h3.product.dao.impl.productdaoimpl" >
   	<property name="sessionfactory" ref="sessionfactory"></property>
   </bean>

运行它

product product = new product();
    product.setproductcode("abc");
    product.setproductdesc("this is product abc");
    	
    productbo productbo = (productbo)appcontext.getbean("productbo");
    productbo.save(product, 100); 

假设save() 不具有事务功能,如果异常抛出由productqohbo.save(),钭只插入一条记录到“product”表,没有记录将被插入到“productqoh'表。这是一个严重的问题,在数据库中打破数据一致性。

3.事务管理

声明“transactioninterceptor' bean,以及”hibernatetransactionmanager' hibernate事务,并且通过必要的属性。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/xmlschema-instance"
xsi:schemalocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <bean id="transactioninterceptor" 
       class="org.springframework.transaction.interceptor.transactioninterceptor">
	<property name="transactionmanager" ref="transactionmanager" />
	<property name="transactionattributes">
	   <props>
		<prop key="save">propagation_required</prop>
	   </props>
	</property>
    </bean>
   
    <bean id="transactionmanager" 
        class="org.springframework.orm.hibernate3.hibernatetransactionmanager">
	  <property name="datasource" ref="datasource" />
	  <property name="sessionfactory" ref="sessionfactory" />
    </bean>

</beans>

事务属性

在事务拦截器,必须定义的事务的属性“传播行为”应使用。这意味着,如果一个事务“productboimpl.save()方法被调用另外的”productqohbo.save()'方法,事务应该怎么传播?它能继续在现有的事务中运行?或者为自己开始一个新的事务。

由spring支持传播的 7种类型:
  • propagation_required – 支持当前事务;如果不存在则创建一个新的。
  • propagation_supports – 支持当前事务;如果不存在执行非事务。
  • propagation_mandatory – 支持当前事务;如果当前不存在事务抛出异常。
  • propagation_requires_new – 创建一个新的事务,如果当前事务暂停。
  • propagation_not_supported – 不支持当前的事务;而始终执行非事务。
  • propagation_never – 不支持当前的事务;如果当前事务存在则抛出异常。
  • propagation_nested – 如果当前存在事务嵌套事务中执行,表现与 propagation_required 一样。
在大多数情况下,可能只需要使用propagation_required。
此外,必须定义方法来支持这个事务属性。方法名支持通配符格式,save*会匹配所有的方法名 以save(...)开始的方法 。

事务管理器

在hibernate事务,需要使用 hibernatetransactionmanager 。 如果只对付纯jdbc,usedatasourcetransactionmanager; 而如果是 jta,需要使用 jtatransactionmanager 。

4.代理工厂bean

创建一个新的代理工厂bean的productbo,并设置“interceptornames”属性。
<!-- product business object -->
   <bean id="productbo" class="com.h3.product.bo.impl.productboimpl" >
   	<property name="productdao" ref="productdao" />
   	<property name="productqohbo" ref="productqohbo" />
   </bean>
 
   <!-- product data access object -->
   <bean id="productdao" class="com.h3.product.dao.impl.productdaoimpl" >
   	<property name="sessionfactory" ref="sessionfactory"></property>
   </bean>
   
   <bean id="productboproxy"
	class="org.springframework.aop.framework.proxyfactorybean">
	<property name="target" ref="productbo" />
	<property name="interceptornames">
		<list>
			<value>transactioninterceptor</value>
		</list>
	</property>
  </bean>

运行它

product product = new product();
    product.setproductcode("abc");
    product.setproductdesc("this is product abc");
    	
    productbo productbo = (productbo)appcontext.getbean("productboproxy");
    productbo.save(product, 100);
代理 bean' productboproxy'和 save()方法是支持事务,现在,里面productbo.save()方法任何异常会导致整个事务回滚,没有数据会被插入到数据库中。

参考

  1. http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/transaction/transactiondefinition.html
  2. http://static.springsource.org/spring/docs/2.5.x/reference/transaction.html

网站声明:
本站部分内容来自网络,如您发现本站内容
侵害到您的利益,请联系本站管理员处理。
联系站长
373515719@qq.com
关于本站:
编程参考手册