Spring中事务的配置学习:
1.心法
Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource、TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分。
DataSource、TransactionManager这两部分只是会根据数据访问方式有所变化。
比如使用Hibernate进行数据访问时,DataSource实际为SessionFactory,TransactionManager的实现为HibernateTransactionManager。
比如使用ibatis进行数据访问时(jdbc方式),DataSource实际为BasicDataSource,TransactionManager的实现为org.springframework.jdbc.datasource.DataSourceTransactionManager< extend AbstractPlatformTransactionManager implements PlatformTransactionManager>。
具体如下图:
2.样例配置<JDBC类型>
<?xml version="1.0" encoding="UTF-8"?> <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:mvc="http://www.springframework.org/schema/mvc" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd"> <context:property-placeholder location="classpath:config/*.properties" /> <!-- 用apache的datasource --> <bean id="dataSource" class="util.db.XBasicDataSource" destroy-method="close" p:driverClassName="${jdbc.driverClassName}" p:url="${jdbc.databaseurl}" p:username="${jdbc.username}" p:password="${jdbc.password}" > <property name="maxActive"><value>${jdbc.maxActive}</value></property> <property name="initialSize"><value>${jdbc.initialSize}</value></property> <property name="maxWait"><value>${jdbc.maxWait}</value></property> <property name="maxIdle"><value>${jdbc.maxIdle}</value></property> <property name="minIdle"><value>${jdbc.minIdle}</value></property> <!-- 只要下面两个参数设置成小于8小时(MySql默认),就能避免MySql的8小时自动断开连接问题 参数百度:DBCP--> <property name="timeBetweenEvictionRunsMillis"><value>14400000</value></property><!-- 4小时 --> <property name="minEvictableIdleTimeMillis"><value>108000000</value></property><!-- 3小时 --> <property name="validationQuery"> <value>SELECT 1</value> </property> <property name="testOnBorrow"> <value>true</value> </property> </bean> <!-- transaction manager, use JtaTransactionManager for global tx --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <!-- 拦截器方式配置事物 --> <tx:advice id="transactionAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="add*" propagation="REQUIRED" rollback-for="java.lang.Exception"/> <tx:method name="append*" propagation="REQUIRED" rollback-for="java.lang.Exception"/> <tx:method name="save*" propagation="REQUIRED" rollback-for="java.lang.Exception"/> <tx:method name="update*" propagation="REQUIRED" rollback-for="java.lang.Exception"/> <tx:method name="modify*" propagation="REQUIRED" rollback-for="java.lang.Exception"/> <tx:method name="edit*" propagation="REQUIRED" rollback-for="java.lang.Exception"/> <tx:method name="delete*" propagation="REQUIRED" rollback-for="java.lang.Exception"/> <tx:method name="remove*" propagation="REQUIRED" rollback-for="java.lang.Exception"/> <tx:method name="init" propagation="REQUIRED" rollback-for="java.lang.Exception"/> <tx:method name="delAndInit" propagation="REQUIRED" rollback-for="java.lang.Exception"/> <tx:method name="execute*" propagation="REQUIRED" rollback-for="java.lang.Exception"/> <tx:method name="test*" propagation="REQUIRED" rollback-for="java.lang.Exception"/> <tx:method name="get*" propagation="REQUIRED" /> <tx:method name="find*" propagation="REQUIRED" read-only="true" /> <tx:method name="load*" propagation="REQUIRED" read-only="true" /> <tx:method name="search*" propagation="REQUIRED" read-only="true" /> <tx:method name="datagrid*" propagation="REQUIRED" read-only="true" /> <tx:method name="*" propagation="REQUIRED" /> </tx:attributes> </tx:advice>
<aop:config> <aop:pointcut id="transactionPointcut" expression="execution(* *..*.service.*.*(..))" /> <aop:advisor pointcut-ref="transactionPointcut" advice-ref="transactionAdvice" /> </aop:config> </beans>
配置解析:
1>.dataSource 中的配置查看相应的类中的参数;如上BasicDataSource类为:
2>. DataSourceTransactionManager中的DataSource必须和SqlSessionFactoryBean连接的数据源一致;DataSourceTransactionManager< extend AbstractPlatformTransactionManager implements PlatformTransactionManager>
3>. tx:method 属性设置
属性对应的TransactionDefinition类
4>.事务的传播属性
Propagation :key属性确定代理应该给哪个方法增加事务行为。这样的属性最重要的部份是传播行为。有以下选项可供使用:PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。
5>.Spring事务的隔离级别(Isolation level)
由隔离级别从低到高:
1. ISOLATION_DEFAULT:这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别。另外四个与JDBC的隔离级别相对应
2. ISOLATION_READ_UNCOMMITTED:这是事务最低的隔离级别,它充许令外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读。
3. ISOLATION_READ_COMMITTED: 保证一个事务不能读到另一个并行事务已修改但未提交的数据。数据提交后才能被读取。避免了脏数据。该级别适应于大多数系统。大多数主流数据库默认的级别。
4. ISOLATION_REPEATABLE_READ:它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。避免了脏读,不可重复读。但是可能出现幻像读。但是也带来更多的性能损失。
5. ISOLATION_SERIALIZABLE 事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻像读。这是花费最高代价但是最可靠的事务隔离级别。
6>.<aop:advisor pointcut-ref="transactionPointcut" advice-ref="transactionAdvice" />
aop:advisor 配置中的pointcut-ref:切点
aop:advisor 配置中的advice-ref:要事务处理的方法
aop中两者的控制方式是:与
符合两者要求的按指定的事务处理方式处理
7>.roll-back
可指定方法指定的回滚方式;
可控制回滚要抛出的异常 和 当抛出某异常时不会滚;
8>.read-only
控制此事务为只读数据,而不能写数据;
3.@Transactional 使用注释直接控制事务
In addition to the XML-based declarative approach to transaction configuration, you can use an annotation-based approach. Declaring transaction semantics directly in the Java source code puts the declarations much closer to the affected code. There is not much danger of undue coupling, because code that is meant to be used transactionally is almost always deployed that way anyway.
The ease-of-use afforded by the use of the @Transactional
annotation is best illustrated with an example, which is explained in the text that follows. Consider the following class definition:
// the service class that we want to make transactional @Transactional public class DefaultFooService implements FooService { Foo getFoo(String fooName); Foo getFoo(String fooName, String barName); void insertFoo(Foo foo); void updateFoo(Foo foo); }
When the above POJO is defined as a bean in a Spring IoC container, the bean instance can be made transactional by adding merely one line of XML configuration:
<!-- from the file context.xml --> <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- this is the service object that we want to make transactional --> <bean id="fooService" class="x.y.service.DefaultFooService"/> <!-- enable the configuration of transactional behavior based on annotations --> <tx:annotation-driven transaction-manager="txManager"/><!-- a PlatformTransactionManager is still required --> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!-- (this dependency is defined somewhere else) --> <property name="dataSource" ref="dataSource"/> </bean> <!-- other <bean/> definitions here --> </beans>
4.总结
把握事务配置三个组成部分即可;
参考资料:http://docs.spring.io/spring/docs/4.1.7.RELEASE/spring-framework-reference/htmlsingle/#transaction