zl程序教程

您现在的位置是:首页 >  后端

当前栏目

Spring框架9:spring实现声明式事务控制

Spring控制事务框架 实现 声明
2023-09-27 14:23:43 时间

本系列笔记均是对b站教程https://www.bilibili.com/video/av47952931 的学习笔记,非本人原创

spring基于xml的声明式事务控制
enter description here
enter description here
enter description here
spring默认使用数据库的隔离级别:
enter description here
事务的传播行为:
enter description here
enter description here
只有查询方法才适用于只读事务
enter description here
什么是事务的存储点呢?存储点是一个事务内部的提交和回滚的节点:如果当前节点内的操作成功,则提交这一段的操作;如果失败,则回滚到上一节点

<!--spring中基于xml的声明式事务配置步骤-->
    <!--1.配置事务管理器-->
    <bean id="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!--2.配置事务的通知
    需要导入事务的约束
    此时我们需要导入事务的约束,tx名称空间和约束,同时也需要aop的
    使用tx:advice配置事务通知
        属性:
            id:给事务通知起一个唯一标志
            transactionManager:给事务通知提供一个事务管理器引用-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <!--4.配置事务的属性
        isolation:用于指定事务的隔离级别,默认值是DEFAULT,表示使用数据库的默认隔离级别

        propagation:用于指定事务的传播行为,默认值是REQUIRED,表示一定会有事务,增删改的选择;查询方法可以选择SUPPORT
        read-only:用于指定事务是否只读,只有查询方法才能设置为true,默认是false
        rollback-for:用于指定一个异常,当产生该异常时事务回滚;产生其他异常时,事务不回滚,没有默认值,表示任何异常都回滚
        no-rollback-for:用于指定一个异常,当产生该异常时事务不回滚;产生其他异常时,事务回滚,没有默认值,表示任何异常都回滚
        timeout:用于指定事务的超时时间,默认值是-1,表示永远不超时;如果指定了数值,以秒为单位
        -->
        <tx:attributes>
            <!--为所有的非查询方法配置属性-->
            <tx:method name="*" propagation="REQUIRED"read-only="false"/>
            <!--为所有的查询方法配置属性(要命名规范)-->
            <tx:method name="find*" propagation="SUPPORTS" read-only="true"></tx:method>
            <!--第二个优先级比第一个高-->
        </tx:attributes>
    </tx:advice>
<!--3. 配置aop中的通用切入点表达式
-->
    <aop:config>
        <aop:pointcut id="pt1" expression="execution(* com.jiading.service.impl.*.*(..))"/>
<!--建立切入点表达式和事务通知的对应关系-->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pt1"></aop:advisor>
    </aop:config>

注意导包的时候要加上spring-tx:

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>

spring基于注解的声明式事务控制

先来配置bean.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:tx="http://www.springframework.org/schema/tx"
       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/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="com.jiading"></context:component-scan>

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/jd_learning"></property>
        <property name="username" value="root"></property>
        <property name="password" value="<密码>"></property>
    </bean>

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!--spring中基于注解的声明式事务配置步骤-->

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

    <!-- 2.开启spring对注解事务的支持-->
    <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
    <!-- 在需要使用事务支持的地方使用@Transactional注解-->


</beans>

可以看到,这里只配置了引入的外部对象,内部的可以由注解完成
可以使用@Transactional注解开启事务支持,这个注解可以加在类上作用于类中所有的方法,也可以加在方法上。如果同时作用,方法上的会覆盖类上的:

package com.jiading.service.impl;

import com.jiading.dao.impl.AccountDaoImpl;
import com.jiading.domain.Account;
import com.jiading.service.IAccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service("accountService")
//在注解中进行配置
@Transactional(propagation = Propagation.SUPPORTS,readOnly = true)
public class AccountServiceImpl implements IAccountService {
    @Autowired
    AccountDaoImpl accountDao;
    @Override
    public Account findAccountById(Integer accountId) {
        Account accountById = accountDao.findAccountById(accountId);
        return accountById;
    }
    @Transactional(propagation = Propagation.SUPPORTS,readOnly = false)
    //可以对方法进行单独配置
    @Override
    public void transfer(String sourceName, String targetName, Float money) {
        Account source = accountDao.findAccountByName(sourceName);
        Account target = accountDao.findAccountByName(targetName);
        source.setMoney(source.getMoney() - money);
        target.setMoney(target.getMoney() + money);
        accountDao.updateAccount(source);
        accountDao.updateAccount(target);
    }
}

那么如何改造为纯注解的方式呢?这个前面已经说过了,这里不再示范