Spring-0216

事务操作

事务概念

  1. 什么是事务?

事务是数据库操作最基本的单元,逻辑上一组操作,要么都成功,如果有一个失败,则都会失败

典型场景:银行转帐

  1. 事务特性:ACID

  1. 原子性:事务不可分割,都成功或都失败

  1. 一致性:操作之前和操作之后他的总量是不变的

  1. 隔离性:多事务操作时,他们之间不会产生影响

  1. 持久性:事务最终要提交,表中数据真正发生变化

搭建事务操作环境

  1. 创建数据库表,添加记录

  1. 完成Service和Dao,完成对象创建和注入

  1. service注入dao,在dao注入JdbcTemplate,在JdbcTemplate注入DataSource

  1. 在dao创建两个方法,一个加钱,一个扣钱;service创建转账方法

  1. 上述代码如果正常执行,是没有问题的,但是如果代码在执行过程中出现异常,则会产生问题。

  1. 使用事务进行解决

  1. 事务操作过程:

  1. 开启事务

  1. 进行业务操作

  1. 对异常进行捕获

  1. 如果没有异常,则提交事务

  1. 如果出现异常,则事务回滚

Spring事务管理介绍

  1. 事务一般添加到service层(业务逻辑层)

  1. 在Spring进行事务管理操作

  1. 有两种方式:==编程式事务管理==和==声明式事务管理==

  1. 一般使用声明式,编程式太麻烦

  1. 声明式事务管理:

  1. 注解方式(常用)

  1. 基于XML配置文件方式(不常用)

  1. 在Spring进行声明式事务管理,==底层使用AOP==

  1. 在Spring事务管理API:

  1. 提供一个接口:代码事务管理器,这个接口针对不同框架提供不同实现类 PlatformTractionManager

  1. 例如针对Jdbc的模版:DataSourceTractionManage

声明式事务管理(注解实现)

  1. 在spring配置文件中配置事务管理器

<!-- 创建事务管理器  -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
       <!-- 注入数据源  -->
       <property name="dataSource" ref="dataSource"></property>
</bean>
  1. 在spring配置文件,开启事务注解

  1. 在spring配置文件引入命名空间

<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.xsd
                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
                           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd" >
  1. 开启事务注解

<!-- 开启事务注解  -->
<tx:annotation-driven transaction-manager="transactionManager">
</tx:annotation-driven>
  1. 在service类上面(或service类方法上面加上事务注解)

@Service
@Transactional
public class UserService {

    @Autowired
    private UserDao userDao;

    //  转账方法
    public void accountMoney(){
        //  扣钱
        userDao.reduceMoney();
        //  加钱
        userDao.addMoney();
    }
}

这个注解可以加在类上面也可以加在方法上面

  1. 加在类上:这个类里面的所有方法都添加事务

  1. 加在方法上:仅仅这个方法添加事务

  1. 一般为了方便,加在类上

  1. 参数配置

  1. Propagation() :事务的传播行为,一个事务的方法被另外一个事务方法调用时,这个事务方法如何进行

  1. 一共有7种行为:REQUIRED REQUIRED_NEW SUPPORTS NOT_SUPPORTED MANDATORY NEVER NESTED

  1. REQUIRED:如果有事务在运行,当前的方法就在这个事务内运行,否则,就启动一个新事物,并在自己的事务内运行

如果单独调用方法1,则会开启事务B;方法2调用时会开启事务A,这时如果调用方法1,则会把方法1加入到事务A中

  1. REQUIRED_NEW:当前的方法必须启动新事物,并且在它自己的事务内运行,如果有事务正在运行,应该将它挂起

方法的执行会启动自己所在的事务,例如方法1一定会启动事务B,方法2一定会启动事务A,会形成一个内外层嵌套关系,内层事务的执行不受外层事务影响,

  1. SUPPORTS:如果有事务在运行,当前的方法就在这个事务内运行,否则它可以不运行在事务中(到时候再理解吧,现在有点抽象)

  1. isolation() :隔离级别

  1. 事务有特性成为隔离性,多事务操作之前不会产生影响。不考虑隔离性会产生很多问题。

  1. 有三个读问题:脏读、不可重复读、幻读

  1. 脏读:一个未提交事务读取到了另一个未提交的事务数据,由于事务可以回滚,如果回滚的话,读的数据就不对了

  1. 不可重复读:一个未提交事务读取到另一个提交事务修改的数据,导致每次读到的数据不一样,是一种现象不是问题

  1. 幻读:一个未提交事务读取到一个提交事务添加的数据,本来不存在的数据可以被读到

  1. 通过设置事务隔离性,解决读问题

@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.REPEATABLE_READ)
  1. timeout() :超时时间,事务需要在一定时间内进行提交,不提交就会做事务回滚,默认值为-1,就是没有设置,我们设置时以秒为单位:

  1. readOnly:是否只读,读:查询操作,写:添加修改操作;默认值是false,可以设置只读,不允许写数据库

  1. rollbackFor:回滚,可以设置哪些异常进行事务回滚. rollbackFor = NullPointerException.class

  1. noRollbackFor:不回滚,设置出现哪些异常时不进行回滚

事务操作(XML声明式事务管理)

  1. 在spring配置文件中进行配置

  1. 配置事务管理器

  1. 配置通知(AOP增强的部分就叫通知)

  1. 配置切入点和切面

<!-- 0. 提前创建好数据源datasource -->

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

<!-- 2. 配置通知   -->
<tx:advice id="txadvice">
       <!--  配置事务参数  -->
       <tx:attributes>
              <!--  指定哪种规则的方法上面添加事务  -->
              <tx:method name="accountMoney" propagation="REQUIRED"/>
       </tx:attributes>
</tx:advice>


<!-- 3. 配置切入点和切面   -->
<aop:config>
       <!--  配置切入点   -->
       <aop:pointcut id="pt" expression="execution(* com.emnets.transaction.service.UserService.*(..))"/>
       <!--  配置切面   -->
       <aop:advisor advice-ref="txadvice" pointcut-ref="pt" />
</aop:config>

事务完全注解方式(声明式事务管理)

  1. 创建配置类,使用配置类代替xml配置文件

@Configuration  // 配置类
@ComponentScan(basePackages = "com.emnets")     //组建扫描
@EnableTransactionManagement        //  开启事务
public class TxConfig {

    //  创建数据库连接池
    @Bean
    public DruidDataSource getDruidDataSource(){

        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/user_db?characterEncoding=utf8");
        dataSource.setUsername("root");
        dataSource.setPassword("123456");
        return dataSource;
    }

    //  创建Jdbc模版对象
    @Bean
    public JdbcTemplate getJdbcTemplate(DataSource dataSource){     //  注意这里没有创建dataSource对象就之间调用了,和AutoWired原理类似

        //  到IOC容器中根据类型找到dataSource
        JdbcTemplate jdbcTemplate = new JdbcTemplate();

        //  注入dataSource
        jdbcTemplate.setDataSource(dataSource);

        return jdbcTemplate;
    }


    //  创建事务管理器的对象
    @Bean
    public DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource){

        DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
        transactionManager.setDataSource(dataSource);
        return transactionManager;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值