Spring5之事务

本文详细介绍了Spring中的声明式事务管理,包括事务的概念、特性、操作过程以及如何通过XML配置和注解方式进行管理。重点讲解了@Transactional注解的参数配置,如propagation、isolation等,并给出了基于注解的事务管理配置示例。
摘要由CSDN通过智能技术生成

事务概念
    1.什么是事务
        (1)是数据库操作最基本的单元,逻辑上的一组操作,要么都成功,要么全失败
        (2)典型场景:银行转账
    2.事务特性
        (1)原子性(要么都成功,一个失败都失败)
        (2)一致性(总量相同)
        (3)隔离性(多个事务之间互不影响)
        (4)持久性(比如数据发生改变是永久性的)
        
        
事务操作(环境搭建)
    1.创建数据库表,添加记录
    2.创建service类,dao接口和实现类,完成对象创建和关系注入
        (1)在service注入dao,在dao实现类jdbctemplate,在jdbctemplate注入datasource
    3.在dao创建加钱和少钱的方法,在service创建转账的方法    
        (1)dao里
        public interface UserDao {
            public void addMoney();
            public void reduceMoney();

        }
        (2)daoimpl里
            @Autowired
            private JdbcTemplate jdbcTemplate;
            //少钱
            @Override
            public void reduceMoney() {
                String sql = "update t_account set money=money-? where username=?";
                jdbcTemplate.update(sql, 100, "lucy");

            }
            //多钱
            @Override
            public void addMoney() {
                String sql = "update t_account set money=money+? where username=?";
                jdbcTemplate.update(sql, 100, "mary");
            }
        (3)service里
            @Autowired
            private UserDao userDao;

            //转账方法
            public  void  accountMoney() {
                //lucy少一百
                userDao.reduceMoney();
                //mary多一百
                userDao.addMoney();
            }
        (4)测试
            @Test
            public  void test() {
                ApplicationContext context =
                        new ClassPathXmlApplicationContext("bean1.xml");
                UserService userService = context.getBean("userService", UserService.class);
                userService.accountMoney();
            }
        
    4.如果代码在执行过程中出现异常
        出现钱少了但另一个人钱没有增加的问题
            //转账方法
            public  void  accountMoney() {
                //lucy少一百
                userDao.reduceMoney();
                //模拟异常
                int i = 10 / 0;
                //mary多一百
                userDao.addMoney();
            }
        (1)用事务来解决,都成功才成功
        (2)事务操作过程(编程式,但通常使用声明式)
                try {
                    //第一步开启事务


                    //第二步开启业务操作
                    //lucy少一百
                    userDao.reduceMoney();
                    //模拟异常
                    int i = 10 / 0;
                    //mary多一百
                    userDao.addMoney();

                    //第三步没有发生异常,提交事务
                } catch (Exception e) {
                    //第四步出现异常,事务回滚
                }
        

事务操作(Spring事务管理介绍)
    1.事务一般添加到service(业务逻辑层)
    2.在Spring里进行事务管理操作
        (1)有两种方式:编程式和声明式事务管理(一般使用后者)

    3.    声明式事务管理
        (1)基于xml配置文件
        (2)基于注解方式(通常使用)
        
    4.在Spring进行声明式的事务管理,底层使用aop原理
    5.Spring事务管理API
        (1)提供了一个接口,代表事务管理器PlatformTransactionManager
        这个接口为不同的框架提供了不同的实现类
        jdbc模板这里使用的是DataSourceManager实现类
        
        
        
Spring声明式事务管理(基于注解)        
    1.在xml文件中配置事务管理器    
        <!-- 创建事务管理器,实际上就是创建这个地方使用的实现类的对象-->
        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <!-- 注入数据源-->
            <property name="dataSource" ref="dataSource"></property>
        </bean>
    2.在xml文件中开启事务注解
        (1)引入名称空间tx
        (2)<!--开启事务注解-->
            <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
    3.在service类(或方法)上面添加事务注解    
        (1)@Transactional,这个注解可以添加到类上或者方法上
        (2)如果把注解添加到类上,则类的所有方法都添加事务
        (3)如果添加到方法上,只为方法添加事务
        (4)我遇到了的问题(视频里没有):
            在过程中遇到了事务注解失效的问题,
            由于数据库里的表默认为myisam,不支持事务操作,需要通过
            ALTER TABLE t_account ENGINE = INNODB;设置成innodb


Spring声明式事务管理(参数配置)
    1.@Transactional()括号里参数配置
    2.(1)propagation:事务传播行为
            多事务方法调用,过程中事务如何管理
            事务方法指对数据库表数据进行变化的操作(比如查询不属于)
            
            举例有一个add方法上有事务,并且在内部调用update方法
            @Transactional
            public void add(){update();}       public void update(){}
            
            Spring框架事务传播行为有七种:
                (1)REQUIRED:如果add方法本身有事务,调用update方法后,update也使用add当前的事务
                                如果add方法没有事务,调用update方法后,创建新事务
                (2)REQUIRED_NEW :使用add方法调用update方法,无论add是否有事务都会创建新的事务
                 还有多种不一一例举
            @Transactional(propagation = Propagation.REQUIRED)
            
      (2)ioslation:事务隔离级别
            (1)有隔离性多事务操作之间才不会受影响
            (2)不考虑隔离性会出现三个读的问题:脏读、不可重复读、虚读
            (3)脏读:一个未提交事务读取到了另一个未提交事务的数据
                例如两个人修改一条记录,一个人修改完的数据被另一个人看见了,
                但数据进行了事务回滚,导致数据变化,读取的数据不准确。
            (4)不可重复读:一个未提交事务读取到另一个提交事务的修改数据
                (正常事务之间没有影响,只有提交事务之后才能读取到新数据)
            (5)虚读:一个未提交事务读取到另一个提交事务的添加数据
            (6)设置隔离性可以解决以上问题(mysql中默认为REPEATABLE READ)
                    READ UNCOMMITTED  三个问题都不能解决
                    READ COMMITTED    能解决脏读问题
                    REPEATABLE READ  不能解决虚读(幻读)问题
                    SERIALIZABLE   都能解决
                @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.REPEATABLE_READ)
      
      (3)timeout:超时时间
            (1)事务设置必须在多长时间内提交,超时则会回滚
            (2)默认值是-1(表示永不超时),秒为单位
      
      (4)readonly:是否只读
            (1)读:查询。写:添加修改删除
            (2)默认值为false,表示读写都可以
            (3)设置值为true,表示只读
            
      (5)rollbackfor:回滚
            (1)设置出现哪些异常进行事务回滚
            
      (6)norollbackfor:不回滚
            (1)设置出现哪些异常不进行回滚
        
        
Spring声明式事务管理(基于xml配置文件)    
    1.在xml文件中
    第一步配置事务管理器
    第二步配置通知(增强的部分在这就是事务)
    第三步配置切入点(方法)和切面(事务加到方法的过程)
        <!-- 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" />
            <!--表示account开头的方法都添加事务-->
            <!--  <tx:method name="account*"/>-->
            </tx:attributes>
        </tx:advice>
        
        <!--3.配置切入点和切面-->
        <aop:config>
            <!--配置切入点-->
            <aop:pointcut id="pt" expression="execution(* com.xlj.spring5.service.UserService.*(..))"/>
            <!-- 配置切面-->
            <aop:advisor advice-ref="txadvice" pointcut-ref="pt"></aop:advisor>
        </aop:config>
        
        
Spring声明式事务管理(完全注解开发)    
    1.配置类
        @Configuration//表示作为配置类
        @ComponentScan(basePackages = "com.xlj")//开启组件扫描
        @EnableTransactionManagement//开启事务

        public class txconfig {

            //创建数据库连接池
            @Bean
            public DruidDataSource getDruidDataSource() {
                DruidDataSource dataSource = new DruidDataSource();
                dataSource.setDriverClassName("com.mysql.jdbc.Driver");
                dataSource.setUrl("jdbc:mysql:///user_db");
                dataSource.setUsername("root");
                dataSource.setPassword("root");
                return dataSource;
            }

            //创建jdbctemplate对象
            @Bean
            public JdbcTemplate getJdbcTemplate(DataSource dataSource) {
                //到ioc容器中根据类型找到datasource
                JdbcTemplate jdbcTemplate = new JdbcTemplate();
                //注入datasource
                jdbcTemplate.setDataSource(dataSource);
                return jdbcTemplate;
            }

            //创建事务管理器对象
            @Bean
            public DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource) {
                DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
                dataSourceTransactionManager.setDataSource(dataSource);
                return dataSourceTransactionManager;
            }
        }

    2.测试
        @Test
        public  void test2() {
            ApplicationContext context =
                    new AnnotationConfigApplicationContext(TxConfig.class);
            UserService userService = context.getBean("userService", UserService.class);
            userService.accountMoney();
        }

    
        
        
        
        
        

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值