Spring之数据库事务管理

一、PlateformTransactionManager

1.源码分析

首先让我们来看一下PlateformTransactionManager接口源码

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

    void commit(TransactionStatus var1) throws TransactionException;

    void rollback(TransactionStatus var1) throws TransactionException;
}

该接口里一共有三个方法,分别是获取事务状态信息、提交和回滚。在Spring中,数据库事务是通过PlateformTransactionManager进行管理的。当事务产生异常,在默认的实现中所有异常都会产生回滚(可以通过修改配置项达到某些异常不回滚或不回滚事务);当无异常时,事务正常提交。

2.DataSourceTransactionManager实现类

public class DataSourceTransactionManager extends AbstractPlatformTransactionManager
		implements ResourceTransactionManager, InitializingBean {

	@Nullable
	private DataSource dataSource;

	private boolean enforceReadOnly = false;
public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager, Serializable

作为实际参与管理对象的事务管理器,DataSourceTransactionManager继承了抽象事务管理器AbstractPlatformTransactionManager,而AbstractPlatformTransactionManager又实现了PlateformTransactionManager。因此在Spring中就可以使用PlateformTransactionManager接口的方法。

二、配置事务管理器和声明式事务

1.声明式事务

声明式事务是一种约定型事务,为保证数据库数据一致性,Spring给了一个约定,当业务不发生异常时(或发生异常,但该异常被配置信息允许提交事务),Spring会让事务管理器自动提交事务,发生异常时则让事务管理器回滚事务(或该异常不被配置信息允许提交)

2.编程式事务

非主流,不建议使用。

3.使用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">

    <!--配置accountService-->
    <bean id="accountService" class="com.lry.service.AccountServiceImpl">
        <property name="accountDao" ref="accountDao"></property>
    </bean>

    <!--配置accountDao-->
    <bean id="accountDao" class="com.lry.dao.AccountDaoImpl">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--配置数据源-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/spring?characterEncoding=utf-8"></property>
        <property name="username" value="root"></property>
        <property name="password" value="123456"></property>
    </bean>

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

    <!--配置事务通知-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
    <!--配置事务属性-->
        <tx:attributes>
            <tx:method name="*" propagation="REQUIRED" read-only="false"/><!--全通配,优先级低-->
            <tx:method name="find*" propagation="SUPPORTS" read-only="true"></tx:method><!--部分选定,此处为所有查询方法,优先级高-->
        </tx:attributes>
    </tx:advice>

    <!--配置AOP-->
    <aop:config>
    <!--配置切入点表达式-->
        <aop:pointcut id="pt1" expression="execution(* com.lry.service.AccountServiceImpl.*(..))"/>
    <!--建立切入点表达式和事务通知的对应关系,告知Spring哪些类需要用事务拦截器进行拦截-->
        <aop:advisor advice-ref="transactiguaonInterceptor" pointcut-ref="pt1"></aop:advisor>
    </aop:config>
</beans>

事务属性详解

isolation:隔离级别,默认值取数据库数据库默认隔离级别

propagation:传播行为,默认值为REQUIRED,表示一定会有事务

timeout:超时时间,默认值为-1,永不超时

readOnly:开启只读,默认false

rollback-for:用于指定一个异常,当执行产生该异常时,事务回滚。产生其他异常,事务不回滚。 没有默认值,任何异常都回滚。

no-rollback-for:用于指定一个异常,当产生该异常时,事务不回滚,产生其他异常时,事务回 滚。没有默认值,任何异常都回滚。

4.使用纯注解配置事务管理器

创建配置类

添加事务驱动管理器注解

@Configuration
@ComponentScan("com.lry")
@Import({JdbcConfig.class, TransactionConfig.class})
@PropertySource("JdbcConfig.properties")
//使用事务驱动管理器
@EnableTransactionManagement
public class SpringConfiguration {
}

实现接口方法,使得返回数据库事务管理器

此处使用DataSourceTransactionManager去定义数据库事务管理器的实例,并把数据源设置给它

public class TransactionConfig {
    @Bean("transactionManager")
    public PlatformTransactionManager createTransactionManager(DataSource dataSource){
        return new DataSourceTransactionManager(dataSource);
    }
}

使用@Transactional注解配置类和类方法

@Service("accountService")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)//将类下所有方法设为查询只读
public class AccountServiceImpl implements IAccountService{
    @Autowired
    private IAccountDao accountDao;

    public Account findById(int id) {
        return accountDao.findById(id);
    }

    public void updateAccount(Account account) {
        accountDao.updateAccount(account);
    }

    @Transactional(propagation = Propagation.REQUIRED, readOnly = false)//将该方法设置为读写
    public void transfer(int sourceAid, int targetAid, float money) {
        System.out.println("执行转账操作");
        //根据ID查询转出用户名
        Account source=accountDao.findById(sourceAid);
        //根据ID查询转入用户名
        Account target=accountDao.findById(targetAid);

        //转出账户减钱
        source.setMoney(source.getMoney()-money);
        //转入账户加钱
        target.setMoney(target.getMoney()+money);

        //更新转出账户
        accountDao.updateAccount(source);
//        int i=3/0;//插入报错语句
        //更新转入账户
        accountDao.updateAccount(target);
    }
}

注意:使用注解@EnableTransactionManagement后,在Spring上下文中使用事务注解@Transactional,Spring就知道采用这个数据库事务管理器管理事务了

5声明式事务约定流程

无论是@Transactional注解还是XML配置,在Spring Ioc容器初始化时,Spring会读入这个注解或者XML配置的事务信息,并保存到一个事务定义类里面以备将来使用(TransactionDefinition接口的子类)。运行时,Spring会拦截注解标注的某一个方法或者类的所有方法。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值