Spring 之声明式事务和 Spring Junit 案例应用详解

(感谢您的关注和点赞支持!)

Spring-test

在前面测试中,每次从spring 容器中获取 bean 都需要实例化 ApplicationContext ,相对麻烦,可以考虑使用 Spring-test 完成测试

Spring Test 是 Spring Framework 提供的一系列测试支持工具,它为开发者提供了在单元测试和集成测试中模拟 Spring 上下文、依赖注入(DI)和事务管理的能力

添加依赖

pom.xml

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>${spring-version}</version>
</dependency>

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-api</artifactId>
    <version>5.8.2</version>
</dependency>

编写测试类

在 src/test/java 下

编写测试类

需要使用 注解 @SpringJUnitConfig

  • xml 方式:

    @SpringJUnitConfig(locations = "classpath:spring.xml")
    public class SpringTestJunit5{
    
    }
    
  • 注解方式:

    @SpringJUnitConfig(SpringTestJunit5.class)
    @ComponentScan("com.wdzl.anno")
    public class SpringTestJunit5{
    
    }
    如果是全注解,则@SpringJUnitConfig 传入配置扫描注解的类
    

测试配中配置依赖

SpringTestJunit5

@SpringJUnitConfig(locations = "classpath:spring.xml")
public class SpringTestJunit {

    @Autowired
    private EmpService empService;

    @Test
    public void test(){

    }
}

全注解方式:

@SpringJUnitConfig(SpringTestJunit5.class)
@ComponentScan("com.wdzl.anno")
public class SpringTestJunit5 {

    @Autowired
    private BookService bookService;

    @Test
    public void testAOP(){
        bookService.save();
    }
}

三、声明式事务

声明式事务(declarative transaction management)是Spring提供的对程序事务管理的方式之一。 Spring的声明式事务顾名思义就是采用声明的方式来处理事务

编写转账业务代码

package com.wdzl.service;

import com.wdzl.dao.IEmpDao;
import com.wdzl.pojo.Emp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
public class EmpService {
    @Autowired
    private IEmpDao empDao;

    public Emp get(Integer empno){
        return empDao.get(empno);
    }

    public List<Emp> queryAll(){
        return empDao.queryAll();
    }

    public void save(Emp emp){
        empDao.save(emp);
    }

    public void update(Emp emp){
        empDao.update(emp);
    }

    /**
     * 转账
     * @param fromId  转出账号
     * @param toId    转入账号
     * @param money   转账金额
     */
    public void trans(Integer fromId,Integer toId,Float money){
        Emp fromEmp = get(fromId);
        Emp toEmp = get(toId);

        //内存修改
        fromEmp.setSalary(fromEmp.getSalary()-money);
        toEmp.setSalary(toEmp.getSalary()+money);

        // 持久化
        empDao.update(fromEmp);
        //假设异常
//        "".substring(9999);

        empDao.update(toEmp);
    }
}

写好后,正常测试,看是否在没有异常时能正常转账;

异常时,部分转账;出现不一致情况,并没回滚。

配置事务

两种常用方式

  • xml 配置
  • 注解

xml 配置方式

只需在spring 配置文件中修改

1. 配置事务管理器

依赖数据源,通过控制数据源来完成事务控制

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

注意:在idea中,配置 tx 命名空间时方法,敲入 <tx:advice> 自动提示,但是一定要注意,选择 tx 的命名空间,

不要选择 cache !!!!!!!!!

<tx:advice id="txadvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="tra*" propagation="REQUIRED" />
        <tx:method name="*" propagation="SUPPORTS"/>
    </tx:attributes>
</tx:advice>
  • propagation 事务的传播行为:
    • REQUIRED : 必须在事务中,如果方法执行时,已经在事务中,则继续使用当前事务;如果没有事务,则重新打开新的事务
    • SUPPORTS : 支持当前事务状态,如果在事务中,则执行当前事务。如果没有,不会新开启事务
    • REQUIRES_NEW : 每次都会重新开启新的事务
3. aop 配置
<aop:config>
    <aop:pointcut id="xx" expression="execution(public * com.wdzl.service..*.*(..))"/>
    <aop:advisor advice-ref="txadvice" pointcut-ref="xx"/>
</aop:config>

注意:上面配置,需要注入前面的 advice 和 切入点 id

4. 测试

通过上面配置,不需要修改任何代码的,直接正常测试调用就可以了

@SpringJUnitConfig(locations = "classpath:spring.xml")
public class SpringTestJunit {

    @Autowired
    private EmpService empService;

    @Test
    public void test(){
        empService.trans(1,2,500);
    }
}

注解配置方式

1. 配置事务管理器

在 spring.xml 中配置

<!--1. 事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>
2. 开启声明式事务注解
<!--2.启用声明式事务注解-->
<tx:annotation-driven/>
3. 方法标注注解

在需要事务支持的方法标注注解 @Transactional

    @Transactional

    /**
     * 转账
     * @param fromId  转出账号
     * @param toId    转入账号
     * @param money   转账金额
     */
    public void trans(Integer fromId,Integer toId,Float money){
        Emp fromEmp = get(fromId);
        Emp toEmp = get(toId);

        //内存修改
        fromEmp.setSalary(fromEmp.getSalary()-money);
        toEmp.setSalary(toEmp.getSalary()+money);

        // 持久化
        empDao.update(fromEmp);
        //假设异常
//        "".substring(9999);

        empDao.update(toEmp);
    }
}
4. 测试
@SpringJUnitConfig(SpringTestJunit5.class)
@ComponentScan("com.wdzl.anno")
public class SpringTestJunit5 {

    @Autowired
    private EmpService empService;

    @Test
    public void testAOP(){
        empService.trans(1,2,500);
    }
}
相关推荐
Allen Bright5 分钟前
【Java基础-26.1】Java中的方法重载与方法重写:区别与使用场景
java·开发语言
苹果酱05676 分钟前
Golang的文件解压技术研究与应用案例
java·vue.js·spring boot·mysql·课程设计
秀儿y10 分钟前
单机服务和微服务
java·开发语言·微服务·云原生·架构
ybq1951334543111 分钟前
javaEE-多线程案例-单例模式
java·开发语言
seasugar27 分钟前
Maven怎么会出现一个dependency-reduced-pom.xml的文件
xml·java·maven
一只淡水鱼6631 分钟前
【mybatis】基本操作:详解Spring通过注解和XML的方式来操作mybatis
java·数据库·spring·mybatis
唐叔在学习1 小时前
【唐叔学算法】第19天:交换排序-冒泡排序与快速排序的深度解析及Java实现
java·算法·排序算法
music0ant1 小时前
Idea 配置环境 更改Maven设置
java·maven·intellij-idea
记得开心一点嘛1 小时前
Nginx与Tomcat之间的关系
java·nginx·tomcat
界面开发小八哥1 小时前
「Java EE开发指南」如何用MyEclipse构建一个Web项目?(一)
java·前端·ide·java-ee·myeclipse