Spring基础学习8——Spring事务处理

本文深入探讨Spring事务处理,解析事务的四大特性:原子性、一致性、隔离性和持久性,详解事务安全问题如脏读、不可重复读和幻读,并介绍Spring事务管理API,包括平台事务管理器、事务定义信息和事务状态等。同时,通过具体案例讲解如何在Spring中实现转账业务流程的事务管理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Spring基础学习8——Spring事务处理

事物特性

原子性:事务不可分割

一致性:事务执行前后数据完整性保持一致

隔离性:一个事务的执行不受其他事务的干扰

持久性:一旦事务结束,数据就持久化到数据库

事务的安全性问题

  • 读问题:

    • 脏读:一个事务读到另一个事务未提交的数据

    • 不可重复读:一个事务读到另外一个事务已经提交的update数据,导致一个事务中多次查询结果不一致

    • 虚读、幻读:一个事务读到另外一个事务已经提交的insert数据,导致一个事务中多次查询结果不一致

  • 些问题

    • 丢失更新

解决读写问题

  • 事务的隔离级别

    • Read uncommitted:未提交读、任何读问题解决不了。

    • Read committed:已提交读,解决脏读,但是不可重复读和虚读有可能发生

    • Repeatable read:重复读,解决脏读和不可重复读,但是虚读有可能发生

    • serializable:解决所有问题

Spring事务管理API

平台事务管理器:PlatformTransactionManager

底层使用jdbc事务管理用:DataSourceTransactionManager

底层用Hibernate事务管理用:HibernateTransactionManager

事务定义信息:TransactionDefinition

事务状态:TransactionStatus

事务管理的API关系

Spring进行事务管理时:首先平台事务管理器根据事务定义信息进行事务的管理,在事务管理过程中,产生各种状态,将这些状态的信息记录到事务状态的对象中

Spring事务传播行为:

对象B调用对象A:

  • 保证多个操作在同一个事务中:

    • PROPAGATION_REQUIRED:(默认值)如果A中有事务,则使用A中的事务,如果A中没有,则会创建一个新事务,将操作进行包裹。

    • PROPAGATION_SUPPORTS:如果A中有事务,则使用A中的事务,如果A中没有,不使用事务

    • PROPAGATION_MANDATORY:如果A中有事务,则使用A中的事务,如果A中没有,爆出异常

  • 保证多个操作不在统一事务中:

    • PROPAGATION_REQUIRES_NEW:如果A中有事务,将A的事务挂起,创新新的事务,只包含自身的操作,如果A中没有,创新新的事务,只包含自身的操作

    • PROPAGATION_NOT_SUPPORTED:如果A中有事务,将A的事务挂起,不使用事务

    • PROPAGATION_NEVER:如果A中有事务,则报异常

  • 嵌套式事务:

    • PROPAGATION_NESTED: 如果A中有事务,按照A的事务执行,执行完成后,设置一个保存点,执行B中的操作,如果没有异常执行通过,有异常则可以选择回滚到初始位置也可回滚到保存点

 

Spring事务案例:

基础业务流程:转款


// 数据库操作接口及其实现类
public interface AccountDao {
    public void  outMoney(String from ,Double money);
    public void  inMoney(String to,Double money);
}

public class AccountDaoImpl extends JdbcDaoSupport implements  AccountDao {
    @Override
    public void outMoney(String from, Double money) {
        this.getJdbcTemplate().update("update account set money = money - ? where name =?",money,from);
    }
    @Override
    public void inMoney(String to, Double money) {
        this.getJdbcTemplate().update("update account set money = money + ? where name =?",money,to );
    }
}

// 服务接口及其实现类
public interface AccountService {
    public void tranfer(String formid, String to,Double money);
}

public class AccountServiceImpl implements AccountService {
    private AccountDao accountDao;

    public void  setAccountDao(AccountDao accountDao){
        this.accountDao = accountDao;
    }
    @Override
    public void tranfer(String from, String to, Double money) {
        accountDao.outMoney(from,money);
        accountDao.inMoney(to,money);
    }
}

// 用于用户调用的服务
<bean id="accountService" class="com.hhh.spring.demo.inter.AccountServiceImpl">
  <property name="accountDao" ref="accountDao"/>
</bean>
// 操作数据库对象
<bean id="accountDao" class="com.hhh.spring.demo.inter.AccountDaoImpl">
  <property name="dataSource" ref="dataSource"/>
</bean>

<!-- 通过context标签引入配置文件-->
<context:property-placeholder location="classpath:jdbcConfigurer.properties"/>
<!-- 设置才c3p0数据库配置-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
  <property name="driverClass" value="${jdbc.driverClass}"></property>
  <property name="jdbcUrl" value="jdbc:mysql://127.0.0.1:3306/homework"/>
  <property name="user" value="root"/>
  <property name="password" value="123456"/>
</bean>

 

加入事务管理的转款

// 数据库操作接口及其实现类不变

// 服务接口及其实现类,
public class AccountServiceImpl implements AccountService {
    private AccountDao accountDao;

    public void  setAccountDao(AccountDao accountDao){
        this.accountDao = accountDao;
    }
		// 在服务中加入平台事务管理模板
    private TransactionTemplate transactionTemplate;

    public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
        this.transactionTemplate = transactionTemplate;
    }

    @Override
    public void tranfer(String from, String to, Double money) {
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
                accountDao.outMoney(from,money);
                accountDao.inMoney(to,money);
            }
        });
    }
}

// 用于用户调用的服务
<bean id="accountService" class="com.hhh.spring.demo.inter.AccountServiceImpl">
	<property name="accountDao" ref="accountDao"/>
	<!--注入事务管理的模板-->
	<property name="transactionTemplate" ref="transactionTemplate"/>
</bean>

<bean id="accountDao" class="com.hhh.spring.demo.inter.AccountDaoImpl">
	<property name="dataSource" ref="dataSource"/>
</bean>

<!--配置平台事务管理器-->
<bean id="transactionManager"      
	class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>

<!--配置事务管理的模板-->
<bean id="transactionTemplate"          
		class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"/>
</bean>

<!-- 通过context标签引入-->
<context:property-placeholder location="classpath:jdbcConfigurer.properties"/>

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
  <property name="driverClass" value="${jdbc.driverClass}"></property>
  <property name="jdbcUrl" value="jdbc:mysql://127.0.0.1:3306/homework"/>
  <property name="user" value="root"/>
  <property name="password" value="123456"/>
</bean>

xml方式声明事务管理,配置事务管理aop增强

// 服务实现类,
public class AccountServiceImpl implements AccountService {
    private AccountDao accountDao;
    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }
    @Override
    public void tranfer(String from, String to, Double money) {
        accountDao.outMoney(from, money);
        int a = 1/0;
        accountDao.inMoney(to, money);
    }
}

<!--配置平台事务管理器-->
 <bean id="transactionManager"          
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
 <property name="dataSource" ref="dataSource"/>
 </bean>

<!--配置事务的增强-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
  <tx:attributes>
  <tx:method name="*" propagation="REQUIRED" isolation="DEFAULT" timeout="-1"/>
  <tx:method name="find" read-only="true"/>
  </tx:attributes>
</tx:advice>

<!--aop的增强-->
<aop:config>
  <aop:pointcut id="pointcut" expression="execution(* com.hhh.spring.demo.inter.AccountServiceImpl.*(..))"/>
  <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"/>
</aop:config>

这里的"配置事务的增强" 配置的是方法的事务规则name:适用的方法(*为任意方法) isolation配置的是隔离规则,read-only:只读选项,timeout:读取超时(-1一直有效)。

"aop增强"配置的的具体的切点和切面

通过注解的方式加入事务管理

// 使用注解,为服务中的每个方法都设置事务规则
@Transactional(isolation = Isolation.DEFAULT,propagation = Propagation.REQUIRED)
public class AccountServiceImpl implements AccountService {
    private AccountDao accountDao;
    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }
    @Override
    public void tranfer(String from, String to, Double money) {
        accountDao.outMoney(from, money);
        int a = 1/0;
        accountDao.inMoney(to, money);
    }
}

<!--配置平台事务管理器-->
 <bean id="transactionManager"    
 			class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
 <property name="dataSource" ref="dataSource"/>
 </bean>

<!--开启注解事务-->
<tx:annotation-driven transaction-manager="transactionManager"/>

上面三个方法的共性是都必须有:

<!--配置平台事务管理器-->
<bean id="transactionManager"      
	class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值