【SSM】Spring事务处理总结

目录

一、事务的基本介绍

二、MySQL事务处理

三、JDBC事务处理

四、Spring的事务处理内容介绍

1.Spring事务处理的核心API

  ①:平台事物管理器PlatformTransactionManager接口

  ②:事务定义TransactionDefinition接口定义如下:

  ③:事务状态TransactionStatus接口定义如下: 

  ④:事务管理器的实现类(这里举三个常用的实现类)

2.解析Spring事务的传播行为 

3.事务管理的API的关系

五、搭建环境(注解方式)

       1.首先使用Maven构建工程,需添加Mysql、Spring等包

       2.添加Spring的配置文件Spring-config.xml 

       3.创建建数据库表

       4.创建数据库表对应的实体类

       5.创建持久层接口及实现类

六、Spring编程式事务处理(入门案例)

      1.基于底层API的编程式事务管理

        2.测试

      2.基于TransactionTemplate的编程式事务管理

七、Spring声明式事务处理(入门案例)

①.基于命名空间的声明式事务管理

②.基于@Transactional的声明式事务管理

八、总结


一、事务的基本介绍

概念:事务一般特指数据库事务(Database Transaction),是指作为一个程序执行单元执行的一系列操作,要么全执行,要么全不执行。

特性:原子性(Atomicity):一个事物是不可分割的工作单位 (从结构上进行处理,保证sql的执行准确)

           一致性(Consistency):事务必须是使数据库从一个以执行状态到另一个一致性状态 (保证业务的一致性)

           隔离性(isolation):一个事务的执行不能被其他事务干扰(用于处理并发情况)

           持久性(Durability):一个事务一旦提交,它对数据库中数据的改变是永久性的(保存到磁盘上)

Spring的事务管理是基于Mysql和JDBC的,所以接下来首先介绍Mysql和JDBC事务

二、MySQL事务处理

https://blog.youkuaiyun.com/weixin_41963657/article/details/89428840

三、JDBC事务处理

JDBC的事务处理是基于Connection的,JDBC通过Connection对象进行事务管理

JDBC默认事务处理是自动提交

事务的相关方法:setAutoCommit设置是否自动提交

                             commit提交事务

                             rollback回滚事务

隔离级别与Mysql处理类似

四、Spring的事务处理内容介绍

1.Spring事务处理的核心API

  ①:平台事物管理器PlatformTransactionManager接口

public interface PlatformTransactionManager {  
       TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;  
       void commit(TransactionStatus status) throws TransactionException;  
       void rollback(TransactionStatus status) throws TransactionException;  
}
  • getTransaction():开启/获取一个事务,通过传递的TransactionDefinition参数来告诉该方法需要开启一个什么样的事务,返回一个TransactionStatus对象
  • commit():用于提交TransactionStatus参数代表的事务
  • rollback():用于回滚TransactionStatus参数代表的事务

  ②:事务定义TransactionDefinition接口定义如下:

public interface TransactionDefinition {  
       int getPropagationBehavior();  
       int getIsolationLevel();  
       int getTimeout();  
       boolean isReadOnly();  
       String getName();  
} 
  • getPropagationBehavior():返回定义的事务传播行为;
  • getIsolationLevel():返回定义的事务隔离级别;
  • getTimeout():返回定义的事务超时时间;
  • isReadOnly():返回定义的事务是否是只读的;
  • getName():返回定义的事务名字。

   ③:事务状态TransactionStatus接口定义如下: 

    public interface TransactionStatus extends SavepointManager {  
           boolean isNewTransaction();  
           boolean hasSavepoint();  
           void setRollbackOnly();  
           boolean isRollbackOnly();  
           void flush();  
           boolean isCompleted();  
    }  
  • isNewTransaction():返回当前事务状态是否是新事务
  • hasSavepoint():返回当前事务是否有保存点
  • setRollbackOnly():设置当前事务应该回滚;
  • isRollbackOnly(():返回当前事务是否应该回滚;
  • flush():用于刷新底层会话中的修改到数据库,一般用于刷新如Hibernate/JPA的会话,可能对如JDBC类型的事务无任何影响;
  • isCompleted():当前事务否已经完成。

    ④:事务管理器的实现类(这里举三个常用的实现类)

  • DataSourceTransactionManager:位于org.springframework.jdbc.datasource包中,数据源事务管理器,提供对单个javax.sql.DataSource事务管理,用于Spring JDBC抽象框架、iBATIS或MyBatis框架的事务管理;
  • JpaTransactionManager:位于org.springframework.orm.jpa包中,提供对单个javax.persistence.EntityManagerFactory事务支持,用于集成JPA实现框架时的事务管理;
  • HibernateTransactionManager:位于org.springframework.orm.hibernate3包中,提供对单个org.hibernate.SessionFactory事务支持,用于集成Hibernate框架时的事务管理;该事务管理器只支持Hibernate3+版本,且Spring3.0+版本只支持Hibernate 3.2+版本;

2.解析Spring事务的传播行为 

        简单来说有一个A方法,当A方法被其他方法调用了,这时就必须指定A方法如何传播。例如:方法可能继续在现有的事务中运行,也可能开启一个新的事务等。

  • PROPAGATION_REQUIRED(常用)支持当前事务,如果当前没有事务,就新建一个事务。
  • PROPAGATIONL SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。
  • PROPAGATION_MANDATORY:支持当前事务,如果当前没有事务,就抛出异常。
  • PROPAGATIONL REQUIRES_ NEW:新建事务,如果当前存在事务,把当前事务挂起。
  • PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
  • PROPAGATIONLNEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
  • PROPAGATIONNESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,就新建一个事务。

举例比如REQUIRED 传播行为:当A()方法调用了B()方法,不管A是否有事务,也不管B是有事务,都会把调用的B方法开启事务,这样就保证了B方法里的步骤一定在一个事务中

3.事务管理的API的关系

        Spring进行事务管理的时候,首先平台事务管理器根据事务定义信息进行事务的管理,在事务管理过程中,产生各种状态,将这些状态及信息记录到事务状态的对象中。

五、搭建环境(注解方式)

       1.首先使用Maven构建工程,需添加Mysql、Spring等包

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.spring</groupId>
    <artifactId>springTransaction</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.41</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.1.7.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>5.1.7.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.1.7.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>5.1.7.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.1.7.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>5.1.7.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.1.7.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.9</version>
        </dependency>
    </dependencies>


</project>

       2.添加Spring的配置文件Spring-config.xml 

   需在配置文件中添加包扫描、配置数据库信息,由于代码中使用了JdbcTemplate所以也要配置Spring的JdbcTemplate方式。

<?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"
       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">
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/mytest"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean>
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <context:component-scan base-package="com.xyz.*"/>

</beans>

       3.创建建数据库表

   这里仅仅为了说明Spring事务,所以简单的建了一张表,person表中只有id、name两个字段

CREATE TABLE person(
    id INT,
    NAME VARCHAR(20)
);

       4.创建数据库表对应的实体类

@Component
public class Person {

    private int id;

    private String name;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

       5.创建持久层接口及实现类

@Repository
public interface personDao {
    void insert(Person person);
    void delete(int id);
    Person query(int id);
}
@Repository
public class personDaoImpl implements personDao {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Override
    public void insert(Person person) {
        String sql = "insert into person(id,name) values(?,?)";
        jdbcTemplate.update(sql,person.getId(),person.getName());
    }

    @Override
    public void delete(int id) {
        String sql = "delete from person where id=?";
        jdbcTemplate.update(sql,id);
    }

    @Override
    public Person query(int id) {
        String sql = "select * from person where id="+id;
        return jdbcTemplate.queryForObject(sql, new RowMapper<Person>() {
            @Override
            public Person mapRow(ResultSet resultSet, int i) throws SQLException {
                Person person = new Person();
                person.setName(resultSet.getString("name"));
                person.setId(resultSet.getInt("id"));
                return person;
            }
        });
    }
}

六、Spring编程式事务处理(入门案例)

      1.基于底层API的编程式事务管理

       由于需使用PlatformTransactionManager、TransactionDefinition、TransactionStatus所以在spring-config.xml文件中配置相关的Bean。

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
</bean>
<bean id="transactionDefinition" class="org.springframework.transaction.support.DefaultTransactionDefinition">

</bean>

 

 

        2.测试

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:Spring-config.xml")
public class test {
    @Autowired
    Person person;
    @Autowired
    private personDao personDao;
    @Autowired
    private PlatformTransactionManager transactionManager;
    @Autowired
    private TransactionDefinition transactionDefinition;

    @Test
    public void demo1(){
        person.setId(1);
        person.setName("张三");
        TransactionStatus transaction = transactionManager.getTransaction(transactionDefinition);
        Person query = personDao.query(2);
        System.out.println(query);
        transactionManager.commit(transaction);
    }
    @Test
    public void demo2(){
        person.setId(2);
        person.setName("李四");
        TransactionStatus transaction = transactionManager.getTransaction(transactionDefinition);
        Person query = personDao.query(2);
        System.out.println(query);
        transactionManager.rollback(transaction);
    }
}

            运行demo1可以看到数据库person表添加了一条数据,但demo2未添加。

      2.基于TransactionTemplate的编程式事务管理

       由于基于底层API的编程式事务方式有些代码过于臃肿,Spring为了简化代码创建了一个TransactionTemplate类,通过该类简化底层API式代码

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:Spring-config.xml")
public class test2 {
    @Autowired
    Person person;
    @Autowired
    private personDao personDao;
    @Autowired
    private TransactionTemplate transactionTemplate;

    @Test
    public void demo1(){
        person.setId(3);
        person.setName("李四");
        transactionTemplate.equals(new TransactionCallback() {
            @Override
            public Object doInTransaction(TransactionStatus transactionStatus) {
                try{
                    personDao.insert(person);
                }catch (Exception e){
                    transactionStatus.setRollbackOnly();
                }
                return null;
            }
        });
    }
}

      同时也需要修改配置文件添加TransactionTemplate的Bean

      TransactionTemplate必须要指定事务管理器,其他的隔离级别等属性可以采取默认

<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
        <property name="transactionManager" ref="transactionManager"/>
</bean>

 

七、Spring声明式事务处理(入门案例)

概述:Spring的声明式事务处理是建立在AOP的基础之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。建议在开发中使用声明式事务,是因为这样可以使得业务代码纯粹干净,方便后期的代码维护。

①.基于<tx>命名空间的声明式事务管理

 首先来看看配置文件,可以看到多了<tx>、<aop>标签,其中<tx>标签是向指定名称的方法添加事务,<aop>是确定方法的位置

<?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"
       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">    <bean id="dataSource"class="org.springfra
mework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/mytest"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean>
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <context:component-scan base-package="com.xyz*"/>
    <bean id="transactionManager"             class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="query" propagation="REQUIRED" read-only="true"/>
            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>
    <aop:config>
        <aop:pointcut id="pointcut" expression="execution(* com.xyz.dao.daoImpl.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"/>
    </aop:config>

</beans>

 

测试代码如下

       可以看出使用了<tx>方式大大减少了代码量

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:Spring-config.xml")
public class test3 {
    @Autowired
    private Person person;
    @Autowired
    private personDao personDao;

    @Test
    public void demo1(){
        person.setId(5);
        person.setName("王五");
        personDao.insert(person);
    }
}


②.基于@Transactional的声明式事务管理

  @Transaction自动进行事务管理,当方法异常时会自动回滚只需将想要事务处理的方法上添加@Transactional注解即可!

     测试:对于下面的代码,运行后控制台仅仅输出了报错信息,而没有输出id=666的person信息,说明事务处理成功,

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:Spring-config.xml")
public class test4 {
    @Autowired
    private Person person;
    @Autowired
    private personDao personDao;

    @Test
    @Transactional
    public void demo1(){
        person.setId(666);
        person.setName("666");
        personDao.insert(person);
        Person p = personDao.query(666);
        System.out.println(p);
        System.out.println(1/0);
    }
}

八、总结

       一般开发中,大多使用<tx>命名空间和@Transaction,当需要进行事务处理的方法较少时使用@Transaction,但是当需要进行事务处理的方法太多时选择<tx>命名空间方式更加简便,毕竟可以根据名称前缀批量进行事务处理。

      不论何种Spring事务处理方式,都需要配置事务管理器

  <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
  </bean>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值