关于事物隔离级别, 脏读, 不可重复读, 幻读的理解, 另有一篇文章比较生动的介绍:
http://zhangjq5.iteye.com/admin/blogs/1893304
spring事务管理相关的接口:
TransactionDefinition:代表一个事物,描述了事务的隔离级别, 超时时间,事务是否只读, 传播规则等等;
TransactionStatus:描述事物的状态;
PlatformTransactionManager:事务管理器接口, 只定义了3个方法:getTransaction()获取事务的状态; commit();rollback(); PlatformTransactionManager是一个接口, 它的实现类需要根据具体的情况来选择, 比如如果用jdbc,则可以选择DataSourceTransactionManager, 如果用Hibernate, 可以选择HibernateTransactionManager;
事务管理器的实现类有多种,根据具体的持久层框架的不同而不同;
spring中的事务传播行为的种类:
PROPAGATION_REQUIRED: 如果当前没有事务,就创建一个事务;如果已经存在事务,则加入事务;
PROPAGATION_SUPPORTS: 如果已经存在事务,则加入事务;如果没有事务,则以非事务的方式执行;
PROPAGATION_MANDATORY: 使用当前事务, 如果没有, 则抛出异常;
PROPAGATION_REQUIRED_NEW: 起动一个新的, 不依赖于环境的 "内部(如果是的话)"事务. 这个事务将被完全 commited 或 rolled back 而不依赖于外部事务, 它拥有自己的隔离范围, 自己的锁, 等等. 当内部事务开始执行时, 外部事务将被挂起, 内务事务结束时, 外部事务将继续执行
PROPAGATION_NOT_SUPPORTED:以非事务的方式执行, 如果当前有事务, 则挂起;
PROPAGATION_NEVER:以非事务的方式执行, 如果当前有事务,则抛出异常;
PROPAGATION_NESTED: 如果当前线程中没有事务, 则按照PROPAGATION_REQUIRED来执行; 如果当前线程中存在事务, 则开始一个 "嵌套的" 事务, 它是已经存在事务的一个真正的子事务.嵌套事务开始执行时, 它将取得一个 savepoint. 如果这个嵌套事务失败, 嵌套事务将回滚到此 savepoint. 外部事务可通过配置或捕获内部事务抛出的Exception来决定是回滚还是继续往下执行. 潜套事务是外部事务的一部分, 只有外部事务结束后它才会被提交, 外部事务回滚则内部事务也会回滚, 不管内部事务有没有提交.
关于PROPAGATION_NESTED和PROPAGATION_REQUIRED_NEW, 有一篇好文章, 我转载过来,防止原文被删除:http://zhangjq5.iteye.com/admin/blogs/1893305
使用spring声明式的事务管理:
大多数情况下,事务会放在services层,spring声明式的事务管理中,需要做以下的工作:
1 把dao,service注入到spring容器(这些dao, service不涉及事务);
2 需要注入一个transactionManager(它需要dataSource);
3 通过TransactionProxyFactoryBean为目标对象(需要事务的dao, service等等)提供事务增强,产生增强后的代理对象.
看代码:
先添加一个CompanyService,
- package services;
- import java.util.List;
- import model.Company;
- import dao.hibernate.CompanyDao;
- public class CompanyService {
- private CompanyDao companyDao;
- public CompanyDao getCompanyDao() {
- return companyDao;
- }
- public void setCompanyDao(CompanyDao companyDao) {
- this.companyDao = companyDao;
- }
- public void insertCompany(Company c){
- //some security check
- companyDao.save(c);
- //some updates
- }
- public void deleteCompany(int id){
- //some security check
- companyDao.deleteById(id);
- // some updates
- }
- public void updateCompany(Company c){
- companyDao.save(c);
- }
- public List list(){
- return companyDao.list();
- }
- }
它调用dao组件执行crud.事务控制一般都放在这一层.
spring事务管理第一种配置方式:为每个目标bean配置一个代理
- <bean id="companyDao" class="dao.hibernate.CompanyDaoImpl">
- <property name="hibernateTemplate" ref="hibernateTemplate" />
- </bean>
- <!-- 需要被增强的bean通常命名为xxxxTarget -->
- <bean id="companyServiceTarget" class="services.CompanyService">
- <property name="companyDao" ref="companyDao" />
- </bean>
- <!-- 事务管理器 -->
- <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
- <property name="dataSource" ref="dataSource" />
- </bean>
- <!-- 被代理之后的service,它具有事务功能,程序中我们就使用它 -->
- <bean id="companyService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
- <!-- 事务管理器 -->
- <property name="transactionManager" ref="txManager" />
- <!-- 需要被代理的目标 -->
- <property name="target" ref="companyServiceTarget" />
- <!-- optimize可选,true代表使用CGLib, false代表使用jdk proxy -->
- <property name="optimize" value="true" />
- <!-- 事务属性, 顺序: PROPAGATION, ISOLATION, readOnly, -Exceptions, +Exceptions -->
- <property name="transactionAttributes">
- <props>
- <prop key="insert*">PROPAGATION_REQUIRED</prop>
- <prop key="update*">PROPAGATION_REQUIRED</prop>
- <prop key="delete*">PROPAGATION_REQUIRED</prop>
- <prop key="list">PROPAGATION_REQUIRED, readOnly</prop>
- <prop key="search*">PROPAGATION_REQUIRED, readOnly</prop>
- </props>
- </property>
- </bean>
测试:
- public class Test {
- public static void main(String[] args) throws InterruptedException, SQLException{
- ApplicationContext c = new ClassPathXmlApplicationContext("spring-test.xml");
- CompanyService s = (CompanyService)c.getBean("companyService");
- List list = s.list();
- System.out.println(list.size());
- s.insertCompany(new Company("www.ddd.com","ddd","wuhan", new Date()));
- }}
你会发现,这里的配置和前面讲的spring aop多么的相同,不错,他们的原理都是一样的,如果你没有了解过spring aop, 建议看一下。
通常情况下,service层需要的事务控制的配置大都相同,而且方法名大都是insertXXX, updateXXX, deleteXXX, searchXXX, checkXXX诸如此类,所以我们可以配置一个可复用的事务代理:
spring事务管理第二种配置方式:目标bean共享代理基类
- <!-- abstract="true"标明它是抽象的 -->
- <bean id="baseTransactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true">
- <property name="transactionManager" ref="txManager" />
- <!-- target被注释掉 -->
- <!--property name="target" ref="companyServiceTarget" /-->
- <property name="transactionAttributes">
- <props>
- <prop key="insert*">PROPAGATION_REQUIRED</prop>
- <prop key="update*">PROPAGATION_REQUIRED</prop>
- <prop key="delete*">PROPAGATION_REQUIRED</prop>
- <prop key="list">PROPAGATION_REQUIRED, readOnly</prop>
- <prop key="search*">PROPAGATION_REQUIRED, readOnly</prop>
- </props>
- </property>
- </bean>
- <bean id="companyService" parent="baseTransactionProxy">
- <property name="target" ref="companyServiceTarget" />
- </bean>
- <bean id="otherService" parent="baseTransactionProxy">
- <property name="target" ref="otherServiceTarget" />
- </bean>
- ......
虽然我们为需要事务增强的bean配置了代理类,但是难保用户还会直接使用目标对象companyServiceTarget; 可以使用拦截器.
spring事务管理第三种配置方式:使用拦截器
- <!-- 配置一个事务拦截器,他对目标对象有事务增强的作用 -->
- <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
- <property name="transactionManager" ref="txManager" />
- <property name="transactionAttributes">
- <props>
- <prop key="*">PROPAGATION_REQUIRED</prop>
- </props>
- </property>
- </bean>
- <!-- 为目标对象自动创建代理 -->
- <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
- <property name="beanNames">
- <list>
- <value>companyServiceTarget</value>
- </list>
- </property>
- <property name="interceptorNames">
- <list>
- <value>transactionInterceptor</value>
- </list>
- </property>
- </bean>
测试:此时可以直接使用companyServiceTarget.
- public class Test {
- public static void main(String[] args) throws InterruptedException, SQLException{
- ApplicationContext c = new ClassPathXmlApplicationContext("spring-test.xml");
- //直接使用目标对象
- CompanyService s = (CompanyService)c.getBean("companyServiceTarget");
- List list = s.list();
- System.out.println(list.size());
- s.insertCompany(new Company("www.ddd.com","ddd","wuhan", new Date()));
- }}
spring事务管理第四种配置方式:使用tx命名空间
- <tx:advice id="txAdvice" transaction-manager="txManager">
- <tx:attributes>
- <tx:method name="insert*" propagation="REQUIRED" />
- <tx:method name="update*" propagation="REQUIRED" />
- <tx:method name="delete*" propagation="REQUIRED" />
- <tx:method name="list" propagation="REQUIRED" read-only="true" />
- </tx:attributes>
- </tx:advice>
- <aop:config>
- <aop:pointcut id="interceptorPointCuts"
- expression="execution(* services.*Service(..))" />
- <aop:advisor advice-ref="txAdvice"
- pointcut-ref="interceptorPointCuts" />
- </aop:config>
使用tx命名空间还能对业务方法做更加细致的事务配置, 下面的表格摘自spring docs, 是一些可配置的参数列表和默认值:
name |
Yes |
Method name(s) with which the transaction attributes are to be associated. The wildcard (*) character can be used to associate the same transaction attribute settings with a number of methods; for example, |
|
propagation |
No | REQUIRED | Transaction propagation behavior. |
isolation |
No | DEFAULT | Transaction isolation level. |
timeout |
No | -1 | Transaction timeout value (in seconds). |
read-only |
No | false | Is this transaction read-only? |
rollback-for |
No |
|
|
|
No |
|
但是这种配置就需要把tx, aop的命名空间加入进来了:臭长臭长的。
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:p="http://www.springframework.org/schema/p"
- 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-2.5.xsd
- http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
- http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
- ......
- </beans>
spring事务管理第五种配置方式:注解
略...
相关推荐
关于内容和需求请参看文章:http://blog.csdn.net/sunxing007/archive/2009/03/17/3999705.aspx#1444224和需求:http://topic.csdn.net/u/20090316/15/5c3ded22-1903-488c-ac87-0ae72fe0722c.html
近年来,光纤通信技术在我国数据通信网络中占有重要地位,因为光纤通信具有传输容量大,传输距离远等特点,而得到了很好的应用。但是光纤在传输过程会由于模式色散和波长色散等因素的影响而产生色散效应,光纤的色散...
如果你希望深入学习,可以阅读《The Linux Command Line》等经典书籍,或者参考CSDN博客上的"一起回顾一下linux常用命令 - sunxing007的专栏"等在线资源,如uuu.rar中可能包含的相关教程或笔记。 记住,Linux命令行...
标题中的“flume-kafka-storm-sunxing.rar”表明这是一个关于Java编程和Linux环境下的数据流处理系统,其中包含了Flume、Kafka和Storm这三个关键组件。这三者都是大数据处理领域的重要工具,用于数据收集、传输和...
文档中还提到了原创作者为“sunxing007”,并提供了在线演示链接。同时,作者要求在转载或使用代码时必须注明其出处。 从文件内容来看,文档中包含了HTML和JavaScript两部分代码。在HTML部分,页面结构被创建,包括...
### 基于Modbus协议的PLC与LabVIEW通讯实现:关键技术解析 #### 引言 在现代工业自动化领域,设备之间的高效通讯是确保生产流程顺畅的关键。Modbus协议作为一种广泛采用的通讯标准,被用于多种设备间的通讯,包括...