Spring 事务管理的详细讲解及使用

文章目录

  • 一、 Spring 事务管理简介
  • 二、Spring 事务管理器
    • 1、Spring 事务管理接口
      • 1.1、 PlatformTransactionManager 接口
      • 1.2、 TransactionDefinition 接口
      • 1.3、 TransactionStatus 接口
    • 2、Spring 中包含的事务管理器
  • 三、 事务的传播行为
  • 四、 Spring 声明式事务管理
    • 1、Jar 包依赖
    • 2、使用 XML 文件方式实现声明式事务管理
      • 2.1、 搭建环境
        • 创建项目
        • 创建实体类
        • 创建持久层
        • 创建业务层
        • 配置 Spring JDBC
      • 2.2、 实现业务案例
        • 修改持久层
        • 修改业务层
        • 创建测试类
      • 2.3、 配置 Spring 声明式事务管理
        • 开启 aop 命名空间
        • 开启 tx 命名空间
        • 配置声明式事务管理
        • 启动 Spring 框架加载多个配置文件
      • 2.4、 声明式事务中属性解释
        • name 属性
        • propagation 属性
        • isolation 属性
        • readonly 属性
        • timeout 属性
        • rollback-for 属性
        • no-rollback-for 属性
    • 3、使用注解方式实现声明式事务管理
      • 1、 @Transactional 介绍
      • 2、 使用注解配置声明式事务管理的实现方式
        • 注册事务管理驱动
        • 使用@Transactional 实现事务控制


一、 Spring 事务管理简介

在 Spring 框架中事务管理有两种方式:一种是传统的编程式事务管理,即通过编写代码实现的事务管理;另一种是基于 AOP 技术实现的声明式事务管理。由于在 Spring 框架中,编程式事务管理很少使用,所以我们只对 Spring 的声明式事务管理进行详细讲解。
Spring 的声明式事务管理在底层采用了 AOP 技术,其最大的优点在于无须通过编程的方式管理事务,只需要在配置文件中进行相关的规则声明,就可以将事务规则应用到业务逻辑中。

Spring 实现声明式事务管理主要有两种方式:

  • 基于 XML 文件方式的声明式事务管理。
  • 通过 Annotation 注解方式的事务管理。

二、Spring 事务管理器

在 Spring 框架中提供了多种事务管理器来进行事务管理。Spring 的事务管理器是基于AOP 实现的。在 Spring 的事务管理器中包含了配置事务传播行为、隔离级别、只读和超时属性,这些属性提供了事务应用的方法和描述策略。
在 Java EE 项目开发经常会使用分层模式,Spring 的事务处理位于业务逻辑层,它提供了针对事务的解决方案。

1、Spring 事务管理接口

在 Spring 的事务模块(spring-tx-5.2.7.RELEASE.jar)中包括事务管理的三个核心接口。

1.1、 PlatformTransactionManager 接口

PlatformTransactionManager 接口是 Spring 提供的事务管理器接口,用于管理事务。Spring 将事务的配置详细信息封装到 TransactionDefinition 对象中,然后通过事务管理器的getTransaction() 方法获得事务的状态(TransactionStatus),并对事务进行下一步的操作。
该接口中提供了三个事务操作方法,具体如下:
在这里插入图片描述

1.2、 TransactionDefinition 接口

TransactionDefinition 接口是事务定义(描述)的对象,它提供了事务相关信息获取的方法,其中包括五个操作,具体如下:
在这里插入图片描述

1.3、 TransactionStatus 接口

TransactionStatus 接口是事务的状态,它描述了某一时间点上事务的状态信息。其中包括六个操作,具体如下:
在这里插入图片描述

2、Spring 中包含的事务管理器

Spring 事务管理的详细讲解及使用_第1张图片

三、 事务的传播行为

事务传播行为是指:多个含有事务的方法相互调用时,事务如何在这些方法间传播。
Spring 事务管理的详细讲解及使用_第2张图片

四、 Spring 声明式事务管理

Spring 声明式事务管理实现方式:

  • 基于 XML 文件方式实现声明式事务管理。
  • 通过 Annotation 注解方式实现声明式事务管理。

1、Jar 包依赖

Spring 核心容器模块:
spring-beans-5.2.7.RELEASE.jar
spring-context-5.2.7.RELEASE.jar
spring-core-5.2.7.RELEASE.jar
spring-expression-5.2.7.RELEASE.jar

Spring JDBC 模块:
spring-jdbc-5.2.7.RELEASE.jar

Spring 事务模块:
spring-tx-5.2.7.RELEASE.jar

Spring AOP 模块:
spring-aop-5.2.7.RELEASE.jar

AspectJ 框架:
aspectjweaver-1.9.5.jar

Spring 整合 AspectJ 框架模块:
spring-aspects-5.2.7.RELEASE.jar

Commons-Loggin 日志:
commons-logging-1.2.jar

数据库驱动:
mysql-connector-java-5.1.48.jar

2、使用 XML 文件方式实现声明式事务管理

2.1、 搭建环境

创建项目

Spring 事务管理的详细讲解及使用_第3张图片

创建实体类

public class Users {
    private int userid;
    private String username;
    private String usersex;

    public int getUserid() {
        return userid;
    }

    public void setUserid(int userid) {
        this.userid = userid;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getUsersex() {
        return usersex;
    }

    public void setUsersex(String usersex) {
        this.usersex = usersex;
    }

    @Override
    public String toString() {
        return "Users{" +
                "userid=" + userid +
                ", username='" + username + '\'' +
                ", usersex='" + usersex + '\'' +
                '}';
    }
}

public class Orders {
    private int orderid;
    private double orderprice;

    public int getOrderid() {
        return orderid;
    }

    public void setOrderid(int orderid) {
        this.orderid = orderid;
    }

    public double getOrderprice() {
        return orderprice;
    }

    public void setOrderprice(double orderprice) {
        this.orderprice = orderprice;
    }

    @Override
    public String toString() {
        return "Orders{" +
                "orderid=" + orderid +
                ", orderprice=" + orderprice +
                '}';
    }
}

创建持久层

public interface UsersDao {
}

public class UsersDaoImpl implements UsersDao {
    private JdbcTemplate jdbcTemplate;

    public JdbcTemplate getJdbcTemplate() {
        return jdbcTemplate;
    }

    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }
}

创建业务层

public interface UsersService {

}
public class UsersServiceImpl implements UsersService {
    private UsersDao usersDao;

    public UsersDao getUsersDao() {
        return usersDao;
    }

    public void setUsersDao(UsersDao usersDao) {
        this.usersDao = usersDao;
    }
}

配置 Spring JDBC

<?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"
       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">

<!--        配置解析Properties文件的工具类-->
    <context:property-placeholder location="db.properties"/>


<!--    配置数据源-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>


<!--    配置JdbcTemplate-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>



<!--    配置持久层-->
    <bean id="usersDao" class="com.bjsxt.dao.impl.UsersDaoImpl">
        <property name="jdbcTemplate" ref="jdbcTemplate"/>
    </bean>



<!--    配置业务层-->
    <bean id="usersService" class="com.bjsxt.service.impl.UsersServiceImpl">
        <property name="usersDao" ref="usersDao"/>
    </bean>
</beans>

2.2、 实现业务案例

业务案例:添加用户的同时添加一个订单。

修改持久层

public interface UsersDao {
    void insertUsers(Users users);
    void insertOrders(Orders orders);
}
public class UsersDaoImpl implements UsersDao {
    private JdbcTemplate jdbcTemplate;

    public JdbcTemplate getJdbcTemplate() {
        return jdbcTemplate;
    }

    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }


    //添加用户
    @Override
    public void insertUsers(Users users) {
        String sql = "insert into users values(default,?,?)";
        Object[] args = new Object[]{users.getUsername(),users.getUsersex()};
        this.jdbcTemplate.update(sql,args);
    }


    //添加订单
    @Override
    public void insertOrders(Orders orders) {
        String sql = "insert into orders values(default,?,null)";
        Object[] args = new Object[]{orders.getOrderprice()};
        this.jdbcTemplate.update(sql,args);
    }
}

修改业务层

public interface UsersService {
    void addUsersAndOrders(Users users, Orders orders);
}

public class UsersServiceImpl implements UsersService {
    private UsersDao usersDao;

    public UsersDao getUsersDao() {
        return usersDao;
    }

    public void setUsersDao(UsersDao usersDao) {
        this.usersDao = usersDao;
    }

    @Override
    public void addUsersAndOrders(Users users, Orders orders) {
        this.usersDao.insertUsers(users);
        this.usersDao.insertOrders(orders);
    }
}

创建测试类

public class Test {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext-service.xml");
        UsersService usersService = (UsersService)applicationContext.getBean("usersService");
        Users users = new Users();
        users.setUsername("HUAWEI");
        users.setUsersex("male");
        Orders orders = new Orders();
        orders.setOrderprice(800);
        usersService.addUsersAndOrders(users,orders);
    }
}

2.3、 配置 Spring 声明式事务管理

开启 aop 命名空间

xmlns:aop="http://www.springframework.org/schema/aop"
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd

开启 tx 命名空间

xmlns:tx="http://www.springframework.org/schema/tx"
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd

配置声明式事务管理

<?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: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/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">
        <import resource="applicationContext-service.xml"/>

<!--        配置事务管理器切面对象-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--        需要注入数据源对象-->
        <property name="dataSource" ref="dataSource"/>
    </bean>


<!--    配置事务管理器属性-->
    <tx:advice id="txAdvice">
        <tx:attributes>
<!--            name:执行受事务控制的方法。配置方法:1.给定完全方法名。2.通过*统配符指定方法名-->
<!--            propagation:配置事务的传播行为-->
<!--            isolation:配置事务的隔离级别-->
            <tx:method name="add*" propagation="REQUIRED" isolation="DEFAULT"/>
        </tx:attributes>
    </tx:advice>


<!--    配置切面-->
    <aop:config>
<!--        配置切点-->
        <aop:pointcut id="txPointcut" expression="execution(* com.bjsxt.service.*.*(..))"/>
<!--        配置切面-->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
    </aop:config>

</beans>

启动 Spring 框架加载多个配置文件

public class Test {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext(new String[]{"applicationContext-service.xml","applicationContext-tx.xml"});
        UsersService usersService = (UsersService)applicationContext.getBean("usersService");
        Users users = new Users();
        users.setUsername("HUAWEI11");
        users.setUsersex("male");
        Orders orders = new Orders();
        orders.setOrderprice(1800);
        usersService.addUsersAndOrders(users,orders);
    }
}

2.4、 声明式事务中属性解释

name 属性

name=”方法名称|方法名称*” 指定受事务控制的方法,支持*通配符。

propagation 属性

propagation=”传播行为名称” 配置事务的传播行为。

isolation 属性

Isolation=”隔离级别名称” 配置事物的隔离级别。

readonly 属性

readonly=”true|false” 是否为只读事务。
true:开启只读事务。由于只读事务不存在数据的修改,因此数据库将会为只读事务提供一些优化手段,会对性能有一定提升。建议在查询中开启只读事务。
false:不开启只读事务,默认为 false。

timeout 属性

timeout=”秒”
timeout 是设置超时属性。以秒为单位。当在限定的时间内不能完成所有操作,就会抛异常。

rollback-for 属性

rollback-for=”异常名称” Spring 默认情况下会对 RunTimeException 类型异常进行事务回滚。如果是 Exception 类型的异常则不回滚。
注意:如果异常被 try{}catch{}了,事务就不回滚了,如果想让事务回滚则必须再抛出异常。

no-rollback-for 属性

no-rollback-for=”异常名称” 当出现什么异常时不滚回事务。

3、使用注解方式实现声明式事务管理

1、 @Transactional 介绍

@Transactional 注解 可以作用于接口、接口方法、类以及类方法上。当作用于类上时,该类的所有 public 方法将都具有该类型的事务属性,同时,我们也可以在方法级别使用该注解来覆盖类级别的定义。
虽然@Transactional 注解可以作用于接口、接口方法、类以及类方法上,但是 Spring 建议不要在接口或者接口方法上使用该注解,因为这只有在使用基于接口的代理时它才会生效。另外, @Transactional 注解应该只被应用到 public 方法上,这是由 Spring AOP 的本质决定的。如果你在 protected、private 或者默认可见性的方法上使用 @Transactional 注解,这将被忽略,也不会抛出任何异常。

2、 使用注解配置声明式事务管理的实现方式

注册事务管理驱动

<?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: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/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">
        <import resource="applicationContext-service.xml"/>

<!--    配置事务管理器的切面-->
    <bean id="txTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>


<!--    注册事务管理驱动-->
    <tx:annotation-driven transaction-manager="txTransactionManager"/>
</beans>

使用@Transactional 实现事务控制

@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT)
public class UsersServiceImpl implements UsersService {
    private UsersDao usersDao;

    public UsersDao getUsersDao() {
        return usersDao;
    }

    public void setUsersDao(UsersDao usersDao) {
        this.usersDao = usersDao;
    }

    @Override
    public void addUsersAndOrders(Users users, Orders orders) {
        this.usersDao.insertUsers(users);
        this.usersDao.insertOrders(orders);
    }
}

你可能感兴趣的:(Spring,spring,java,经验分享)