Spring的事物操作学习记录

117 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第10天,点击查看活动详情

Spring 的事务,可以说是 Spring AOP 的一种实现。

AOP面向切面编程,即在不修改源代码的情况下,对原有功能进行扩展,通过代理类来对具体类进行操作。

spring是一个容器,通过spring这个容器来对对象进行管理,根据配置文件来实现spring对对象的管理。

spring的事务声明有两种方式,编程式和声明式。spring主要是通过“声明式事务”的方式对事务进行管理,即在配置文件中进行声明,通过AOP将事务切面切入程序,最大的好处是大大减少了代码量。

Spring事务执行原理通过创建一个BeanFactoryTransactionAttributeSourceAdvisor,并把TransactionInterceptor注入进去,而TransactionInterceptor实现了Advice接口。而Spring Aop在Spring中会把Advisor中的Advice转换成拦截器链,然后调用。

执行流程

  1. 获取对应事务属性,也就是获取@Transactional注解上的属性
  2. 获取TransactionManager,常用的如DataSourceTransactionManager事务管理
  3. 在目标方法执行前获取事务信息并创建事务
  4. 回调执行下一个调用链
  5. 一旦出现异常,尝试异常处理,回滚事务
  6. 提交事务\

具体分析

事物操作

1.事物

事务在项目开发过程非常重要,涉及到数据的一致性的问题,不容马虎!

事务管理是企业级应用程序开发中必备技术,用来确保数据的完整性和一致性。

事务就是把一系列的动作当成一个独立的工作单元,这些动作要么全部完成,要么全部不起作用。 事物四个属性

  • 1.原子性 :事务是原子性操作,由一系列动作组成,事务的原子性确保动作要么全部完成,要么完全不起 作用 -一致性 :一旦所有事务动作完成,事务就要被提交。数据和资源处于一种满足业务规则的一致性状态中
  • 隔离性 :可能多个事务会同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏
  • 持久性 :事务一旦完成,无论系统发生什么错误,结果都不会受到影响。通常情况下,事务的结果被写到持久化存储器中

2.事物操作

例:银行转账 转帐环境:Service(业务操作:创建转账方法、调用dao两个方法) Dao(数据库操作不写业务:创建两个方法:少钱方法、多钱方法)

1.创建数据库

图片.png

2.创建Service,搭建Dao,完成对象创建和注入关系

:Service注入Dao,在FDao注入JdbcTemplate,在JdbcTemplate注入DataSource

  • 接口类
package com.jdbc.account.service;

public interface UserDao {
    //多钱
    public void addMoney();
    //少钱
    public void reduceMoney();
}

  • 实现类
package com.jdbc.account.service;

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

@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,"zhang");
    }
//少钱 l转帐给zhang 100元
    @Override
    public void reduceMoney() {
        String sql = "update t_account set money = money-? where username=?";
        jdbcTemplate.update(sql,100,"lic");
    }
}

  • Service
package com.jdbc.account.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService {
    //注入dao
    @Autowired
    private UserDao userDao;
    //转账操作,业务逻辑层
    public void accountMoney() {
        //lic少一百
        userDao.reduceMoney();
        //zhang 多一百
        userDao.addMoney();
    }
}

测试

package com.jdbc.account.service;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class testMoney {
    @Test
    public  void testAccount() {
        ApplicationContext context = new ClassPathXmlApplicationContext("bean6.xml");
        UserService userService = context.getBean("userService", UserService.class);
        userService.accountMoney();
    }
}

  • 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:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
                           http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    <!--开启组件扫描-->
    <context:component-scan base-package="com.jdbc.account"></context:component-scan>
    <!--数据库连接池-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
        <property name="url" value="jdbc:mysql://localhost:3306/test"/>
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="username" value="root"/>
        <property name="password" value=""/>
     </bean>
    <!--jdbctemplate对象-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <!--注入dataSource-->
        <property name="dataSource" ref="dataSource"></property>
     </bean>
</beans>

3.当处理事物时出现异常

使用事物进行异常处理 将事物最好加入到JavaEE三层结构里面的Service层(业务逻辑层)

  • 使用声明式事物管理 1.基于注解方式 2.基于xml配置文件方式

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

API:事物管理器:接口针对不同的框架提供不同的实现类

流程: 1.开启事物 2.进行业务操作 3.如果没有异常,进行提交结果到数据库 4.如果出现异常,进行事物回滚,结果不提交数据库