Welcome everyone

Spring必知必会 事务

java 汪明鑫 343浏览 0评论

扯淡

这个东西还是遇到过不少次的

而且基本每本Spring书籍都会涉及

那么Spring事务到底重要吗?我觉得不多重要,至少和IOC、AOP比就算个弟弟。

那需要学习嘛,当然需要,

既然是复习Spring理论输出的博客,当然少不了事务

也许你无意间就看到项目代码中出现个@Transactional

上个月听我们组老哥面试校招生,每次快结束都要问你知道Spring事务传播机制吗?

我觉得在校生根本接触不到Spring事务传播,除非死记硬背,可能老哥为了考察知识面把,或者学习Spring到底认真不认真

这个事务传播机制大多直接默认就完事了

记得去年我面试的时候也问过Spring事务,也问过Spring事务怎么配,当时回答过xml配置aop的方式配置事务

 

ACID

  • 原子性 Atomicity   一个事务中的所有操作,或者全部完成,或者全部不完成
  • 一致性 Consistency  数据始终保持一致,数据不会凭空产生或消息
  • 隔离性 Isolation    多个事务并发执行,不相互影响
  • 持久性 Durability   事务一旦执行结束,就产生持久影响

 

 

Spring事务接口一览

 

PlatformTransactionManager

org.springframework.transaction.PlatformTransactionManager

Spring事务管理顶级接口

可以集成不同的数据框架,实现不同平台下的事务管理

 

 

public interface PlatformTransactionManager {
    TransactionStatus getTransaction(TransactionDefinition var1) throws TransactionException;

    void commit(TransactionStatus var1) throws TransactionException;

    void rollback(TransactionStatus var1) throws TransactionException;
}

 

一共3个接口方法

1,getTransaction 获取 TransactionStatus

2,commit 提交事务

3,rollback回滚事务

 

AOP配置事务(XML)

 

先看一个配置事务的例子,

是我从我的github一个项目粘出来的

<?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: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/aop 
       					   http://www.springframework.org/schema/aop/spring-aop.xsd
       					   http://www.springframework.org/schema/context 
       					   http://www.springframework.org/schema/context/spring-context.xsd
       					   http://www.springframework.org/schema/tx 
       					   http://www.springframework.org/schema/tx/spring-tx.xsd">
	
	<!-- 公共配置项 -->
	<!-- 1.1 加载properties文件 -->
	<context:property-placeholder location="classpath:jdbcInfo.properties"/>
	
	<!-- 1.2 配置数据源 -->
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="driverClass" value="${jdbc.driverClass}"></property>
		<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
		<property name="user" value="${jdbc.user}"></property>
		<property name="password" value="${jdbc.password}"></property>
	</bean>
	
	<!-- 2. 配置SessionFactory -->
	<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
		<property name="dataSource" ref="dataSource"></property>
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
				<prop key="hibernate.show_sql">true</prop>
				<prop key="hibernate.format_sql">true</prop>
			</props>
		</property>
		<property name="mappingLocations" value="classpath:pers/wmx/*/domain/*.hbm.xml"></property>
	</bean>
	
	<!-- 3.事务管理 -->
	<!-- 3.1 事务管理器 -->
	<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<property name="sessionFactory" ref="sessionFactory"></property>
	</bean>
	
	<!-- 3.2 事务详情  
		* 增删改:读写;查询:只读
	-->
	<tx:advice id="txAdvice" transaction-manager="txManager">
		<tx:attributes>
			<tx:method name="**" propagation="REQUIRED"/>  
			<tx:method name="add*" />
			<tx:method name="update*"/>
			<tx:method name="delete*"/>
			<tx:method name="find*"  />
		</tx:attributes>
	</tx:advice>
	<!-- 3.3 aop编程 -->
	<aop:config>
		<aop:advisor advice-ref="txAdvice" pointcut="execution(* pers.wmx.*.service..*.*(..))"/>
	</aop:config>
	
	<!-- 导入其他配置文件 -->
	<import resource="applicationContext-user.xml"/>
	<import resource="applicationContext-product.xml"/>
	<import resource="applicationContext-reply.xml"/>
	<import resource="applicationContext-order.xml"/>
	<import resource="applicationContext-orderitem.xml"/>

</beans>

 

1-配置数据源
2-配置sessionfactory
3-配置事务
4-配置aop

 

当然我们也可以用其他的事务管理器

<!-- 事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <!-- 数据源 -->
    <property name="dataSource" ref="dataSource" />
</bean>

 

 

有了上面这个例子,我们一定对Spring事务有了些感觉

继续往下看

 

TransactionDefinition

事务定义信息(事务隔离级别、传播行为、超时、只读、回滚规则)

描述了事务策略如何应用到方法上

 

 

package org.springframework.transaction;

import java.sql.Connection;

public interface TransactionDefinition {

	int PROPAGATION_REQUIRED = 0;

	int PROPAGATION_SUPPORTS = 1;

	int PROPAGATION_MANDATORY = 2;

	int PROPAGATION_REQUIRES_NEW = 3;

	int PROPAGATION_NOT_SUPPORTED = 4;

	int PROPAGATION_NEVER = 5;

	int PROPAGATION_NESTED = 6;

	int ISOLATION_DEFAULT = -1;

	int ISOLATION_READ_UNCOMMITTED = Connection.TRANSACTION_READ_UNCOMMITTED;

	int ISOLATION_READ_COMMITTED = Connection.TRANSACTION_READ_COMMITTED;

	int ISOLATION_REPEATABLE_READ = Connection.TRANSACTION_REPEATABLE_READ;

	int ISOLATION_SERIALIZABLE = Connection.TRANSACTION_SERIALIZABLE;

	int TIMEOUT_DEFAULT = -1;

        //传播行为
	int getPropagationBehavior();

	//隔离级别
	int getIsolationLevel();

	//超时时间:就是指一个事务所允许执行的最长时间,如果超过该时间限制但事务还没有完成,则自动回滚事务
	int getTimeout();

	//是否只读:只读操作 or 读写操作
	boolean isReadOnly();

	//事务名字
	String getName();

}

事务的隔离级别和传播行为都定义到这个接口里
事务的隔离级别就不说了,见mysql事务隔离级别即可

简单的看下事务的传播行为:

事务传播指的就是当一个事务方法被另一个事务方法调用时,这个事务方法应该如何进行。

如:methodA事务方法调用methodB事务方法时,methodB是继续在调用者methodA的事务中运行呢,还是为自己开启一个新事务运行,这就是由methodB的事务传播行为决定的。

 

 

 

/**
 * Support a current transaction; create a new one if none exists.
 * Analogous to the EJB transaction attribute of the same name.
 * <p>This is typically the default setting of a transaction definition,
 * and typically defines a transaction synchronization scope.
 */
int PROPAGATION_REQUIRED = 0;

上面就是Spring事务的默认传播行为,一般都直接使用默认的了,至少我目前没看到需要设置传播行为的地方

 

@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
 methodB();
// do something
}

@Transactional(propagation = Propagation.REQUIRED)
public void methodB() {
    // do something
}

单独调用methodB方法时,因为当前上下文不存在事务,所以会开启一个新的事务。
调用methodA方法时,因为当前上下文不存在事务,所以会开启一个新的事务。当执行到methodB时,methodB发现当前上下文有事务,因此就加入到当前事务中来。

 

TransactionStatus

事务的状态

 

public interface TransactionStatus extends SavepointManager, Flushable {

        //是否是新创建的事务
	boolean isNewTransaction();

	//是否有 Savepoint
	boolean hasSavepoint();

	//设置为只回滚
	void setRollbackOnly();

        //是否为只回滚
	boolean isRollbackOnly();

	@Override
	void flush();

        //事务是否已执行完
	boolean isCompleted();

}

 

PlatformTransactionManager.getTransaction返回一个 TransactionStatus 对象,可能代表一个新的或已经存在的事务

这就是isNewTransaction方法存在的意义:当前事务是否当前方法所创建的,只有创建事务的方法,才能且应该真正的提交事务(
commit(TransactionStatus status)

 

Spring Boot配置事务

spring boot 不需要开发者显式地配置@EnableTransactionManagement,已经自动配置了

 

指定事务管理器

在Spring容器中,我们手工注解@Bean 将被优先加载,框架不会重新实例化其他的 PlatformTransactionManager 实现类。

@Configuration
@MapperScan(basePackages = "xxx.mapper", markerInterface = BaseMapper.class)
@ComponentScan
public class XxxConfiguraion {

    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource) throws SQLException {
        return new DataSourceTransactionManager(dataSource);
    }
}

 

@Transactional(rollbackFor=Exception.class) 
    public void methodName() {
       // 不会回滚  需要补获
       throw new Exception("...");
    } 

@Transactional(rollbackFor=Exception.class) 
    public void methodName1() {
       // 会回滚
       throw new RuntimeException("...");
    } 

 

@Transactional 一般注解在调用db接口的service方法上

 

指定隔离级别
@Transactional(propagation=Propagation.REQUIRES_NEW)

 

readOnly=true只读,不能更新,删除
@Transactional (propagation = Propagation.REQUIRED,readOnly=true)

 

设置超时时间
@Transactional (propagation = Propagation.REQUIRED,timeout=30)

 

设置数据库隔离级别
@Transactional (propagation = Propagation.REQUIRED,isolation=Isolation.DEFAULT)

 

参考

【可能是最漂亮的 Spring 事务管理详解】-芋道源码

https://mp.weixin.qq.com/s?__biz=MzUzMTA2NTU2Ng==&mid=2247484702&idx=1&sn=c04261d63929db09ff6df7cadc7cca21&chksm=fa497aafcd3ef3b94082da7bca841b5b7b528eb2a52dbc4eb647b97be63a9a1cf38a9e71bf90&token=165108535&lang=zh_CN#rd

 

【SpringBoot事务注解详解】

https://www.jianshu.com/p/cddeca2c9245

 

【Spring事务(4):事务属性之7种传播行为】

https://blog.csdn.net/soonfly/article/details/70305683

 

 

转载请注明:汪明鑫的个人博客 » Spring必知必会 事务

喜欢 (0)

说点什么

您将是第一位评论人!

提醒
avatar
wpDiscuz