Spring5 框架 ---- 事务操作

举报
在人间负债^ 发表于 2024/11/26 17:19:07 2024/11/26
【摘要】 1. 事务概念 1. 什么是事务事务是数据库操作最基本单元,逻辑上一组操作,要么都成功,如果有一个操作失败,那么所有操作都将失败。典型应用场景:银行转账 2. 事务的四个特性(ACID)原子性:不可分割一致性:操作之前和操作之后总量不变隔离性:多事务操作时,每个事务之间相互独立持久性:事务提交之后,数据发生变化 2. 搭建事务操作环境 1. 创建数据库表,添加记录 2. 创建service...

1. 事务概念

1. 什么是事务

  1. 事务是数据库操作最基本单元,逻辑上一组操作,要么都成功,如果有一个操作失败,那么所有操作都将失败。
  2. 典型应用场景:银行转账

2. 事务的四个特性(ACID)

  1. 原子性:不可分割
  2. 一致性:操作之前和操作之后总量不变
  3. 隔离性:多事务操作时,每个事务之间相互独立
  4. 持久性:事务提交之后,数据发生变化

2. 搭建事务操作环境

image.png

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

image.png

2. 创建service,搭建dao,完成对象创建和注入关系

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

package com.fickler.spring5.service;

import com.fickler.spring5.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @author dell
 * @version 1.0
 */

@Service
public class UserService {

    //注入dao
    @Autowired
    private UserDao userDao;

}

package com.fickler.spring5.dao;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

/**
 * @author dell
 * @version 1.0
 */

@Repository
public class UserDaoImpl implements UserDao{

    @Autowired
    private JdbcTemplate jdbcTemplate;

}

3. 在dao创建两个方法:多钱和少钱的方法,在service创建方法(转账的方法)

package com.fickler.spring5.dao;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

/**
 * @author dell
 * @version 1.0
 */

@Repository
public class UserDaoImpl implements UserDao{

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public void addMoney() {

        String sql = "update t_account set money = money - ? where username = ?";
        jdbcTemplate.update(sql, 100, "lucy");

    }

    @Override
    public void reduceMoney() {

        String sql = "update t_account set money = money + ? where username = ?";
        jdbcTemplate.update(sql, 100, "mary");

    }
}

package com.fickler.spring5.service;

import com.fickler.spring5.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @author dell
 * @version 1.0
 */

@Service
public class UserService {

    //注入dao
    @Autowired
    private UserDao userDao;

    public void accountMoney(){

        userDao.reduceMoney();
        userDao.addMoney();

    }

}

image.png

4. 上面,如果正常执行没有问题,但是如果代码执行过程中出现异常,有问题

  1. 模拟异常
    public void accountMoney(){

        userDao.reduceMoney();

        int i = 10 / 0;

        userDao.addMoney();

    }
  1. 事务操作过程
    public void accountMoney() {

        try {

            //第一步 开启事务

            //第二步 进行业务操作
            userDao.reduceMoney();

            int i = 10 / 0;

            userDao.addMoney();

            //第三步 没有发生异常,提交事务

        } catch (Exception e) {

            //第四步 出现异常,事务回滚

        }

    }

3. Spring事务管理介绍

1. 事务添加到JavaEE三层结构里面Service层(业务逻辑层)

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

两种方式:编程式事务管理声明式事务管理(使用)

3. 声明式事务管理

  1. 基于注解方式
  2. 基于 xml 配置文件方式

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

5. Spring事务管理API

提供一个接口,代表事务管理器,这个接口针对不同的框架提供不同的实现类

image.png

4. 注解声明式事务管理

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

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

2. 在spring配置文件,开启事务注解

  1. 在 spring 配置文件引入名称空间 tx
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       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">
</beans>
  1. 开启事务注解
    <!--开启事务注解-->
    <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>

3. 在 service 类上面(或者service类里面方法上面)添加事务注解

@Service
@Transactional
public class UserService {
}
  1. @Transactional ,这个注解既可以添加到类上面也可以添加到方法上面
  2. 如果把这个注解添加到类上面,这个类里面所有的方法都添加事务
  3. 如果把这个注解添加到方法上面,为这个方法添加事务

5. 声明事务管理参数配置

1. 在service类上面添加注解@Transactional,这个注解里面可以配置事务相关参数

2. propagation:事务传播行为

当一个事务方法被另一个事务方法调用时候,这个事务方法如何进行

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

image.png

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

image.png

  1. SUPPORTS
    如果有事务在运行,当前的方法就在这个事务内运行,否则它可以不允许在事务中

image.png

事务的传播行为可以由传播属性指定。Spring 定义了 7 种类传播行为。

image.png

3. ioslation:事务隔离级别

  1. 事务有特性成为隔离性,多事务操作之间不会产生影响。不考虑隔离性产生很多问题
  2. 有三个读问题:脏读、不可重复读、虚(幻)读
  3. 脏读:一个未提交事务读取到另一个未提交事务的数据

image.png

  1. 不可重复读:一个未提交事务读取到另一提交事务修改数据

image.png

  1. 幻读:一个未提交事务读取到另一提交事务添加数据
  2. 解决:设置事务隔离性,解决读问题

image.png

MySql 默认的隔离级别是 REPEATABLE READ(可重复读)

4. timeout:超时时间

  1. 事务需要在一定时间内进行提交,如果不提交进行回滚
  2. 默认值是 -1,设置时间以秒单位进行计算

5. readOnly:是否只读

  1. 度:查询操作,写:添加修改删除操作
  2. readOnly 默认值是 false,表示可以查询,可以添加修改删除操作
  3. 设置 readOnly 值是 true,设置成 true 之后,只能查询

6. rollbackFor:回滚

设置出现哪些异常进行事务回滚

7. noRollbackFor:不回滚

设置出现哪些异常不进行事务回滚

6. XML声明式事务管理

在spring配置文件中进行配置

第一步 配置事务管理器
第二步 配置通知
第三步 配置切入点和切面

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       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">

    <!--开启组件扫描-->
    <context:component-scan base-package="com.fickler"></context:component-scan>

    <!-- 数据库连接池 -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
        <property name="url"
                  value="jdbc:mysql://localhost:3306/user_db?useUnicode=true&amp;characterEncoding=utf8&amp;serverTimezone=UTC&amp;useSSL=false&amp;rewriteBatchedStatements=true"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    </bean>

    <!--JdbcTemplate对象-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <!--注入dataSource-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>

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

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

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

</beans>

7. 完全注解声明式事务管理

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

package com.fickler.spring5.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;

/**
 * @author dell
 * @version 1.0
 */

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

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

        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setDriverClassName("com.alibaba.druid.pool.DruidDataSource");
        druidDataSource.setUrl("jdbc:mysql://localhost:3306/user_db?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC&useSSL=false&rewriteBatchedStatements=true");
        druidDataSource.setUsername("root");
        druidDataSource.setPassword("root");

        return druidDataSource;

    }

    //创建JdbcTemplate对象
    @Bean
    public JdbcTemplate getJdbcTemplate(DataSource dataSource){ //到ioc容器中根据类型找到dataSource

        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        jdbcTemplate.setDataSource(dataSource);

        return jdbcTemplate;

    }

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

        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource);

        return dataSourceTransactionManager;

    }

}

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。