如何使用测试类,测试spring项目的事务是否生效

测试类中其实 可以使用很多注解,很方便的实现你想要的功能:

1) 事务管理: 测试完毕后自动回滚

2) 加载配置文件

3) 使用spring的注入特性:@Autowired 等的使用

4) AOP 功能:在 test方法的前后吗,执行代码进行 初始化或销毁资源等操作

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;

/**
 * @author stormfeng
 * @date 2020-11-23  15:51
 */
@RunWith(SpringJUnit4ClassRunner.class)  // 支持使用spring的个性化注解,比如 @Autowired 
@ContextConfiguration(classes = {DatasourceConfig.class, DaoImpl.class}) // 加载所需的 bean 到整个 test环境中 
@TestPropertySource(value = "classpath:jdbc.properties")  // 获取test目录下的 classpath 文件配置  
@Rollback(true) // 默认为true,自动回滚 @Transactional注解的方法,最终 数据库将不会 被改变 
// @TransactionConfiguration(defaultRollback = false)  //已过期,请用 @Rollback 或者 @Commit 
public class DaoConfigTest {

    // CREATE TABLE T_TEST (ID INT,NAME VARCHAR(50)) 
    String TABLE = "T_TEST";

    @Autowired
    Dao dao;

    @Transactional(value = "yourManagerName", rollbackFor = Exception.class)
    @Before
    public void testBefore() {
        List<Map<String, Object>> maps = dao.queryList("SELECT * from " + TABLE);
        System.out.println("before: " + maps);
    }

    /**
     * 测试是否会 INSERT 成功,分别注解 @Rollback(true)  和 @Rollback(false) 试一下 
     */
    @Transactional(value = "yourManagerName", rollbackFor = Exception.class)
    @Test
    public void test01() {
        int i = dao.update("TRUNCATE TABLE  " + TABLE1);
        System.out.println(i);
        i = dao.update("INSERT INTO " + TABLE + " VALUES(1,'1') ");
        System.out.println(i);

    }

    /**
     * 测试异常时的事务管理: 配置 @Rollback(false) ,测试一下事务是否在异常后回滚  
     */
    @Transactional(value = "yourManagerName", rollbackFor = Exception.class)
    @Test
    public void test02() {
        int i = dao.update("INSERT INTO " + TABLE + " VALUES(222,'2222') ");
        int a = 1/0 ; 
        System.out.println(i);
    }

    @After
    @Test
    public void testAfter() {
        List<Map<String, Object>> maps = dao.queryList("SELECT * FROM " + TABLE);
        System.out.println("after:" + maps);        
    }

}

上文所需的DatasourceConfig.class,初始化数据源,源码参考如下:

/**
 * 初始化数据源,jdbctemplate对象,事务对象
 * @author stormfeng
 * @date 2020-09-16  17:24
 */
@EnableTransactionManagement
@Configuration
public class DatasourceConfig {

    @Bean
    public DataSource dataSource(@Value("${oracle.jdbc.driverClass}") final String driverClassName,
                                      @Value("${oracle.jdbc.dataSourceClass}") final String dataSourceClass,
                                      @Value("${oracle.jdbc.url}") final String jdbcUrl,
                                      @Value("${audit.jdbc.username}") final String username,
                                      @Value("${audit.jdbc.password}") final String password,

                                      @Value("${hikaricp.minimumIdle}") final Integer minimumIdle,
                                      @Value("${hikaricp.maximumPoolSize}") final Integer maximumPoolSize,
                                      @Value("${hikaricp.connectionTimeout}") final Long connectionTimeout,
                                      @Value("${hikaricp.maxLifetime}") final Long maxLifetime,
                                      @Value("${hikaricp.idleTimeout}") final Long idleTimeout,
                                      @Value("${hikaricp.readOnly}") final Boolean reauditOnly,
                                      @Value("${hikaricp.connectionInitSql}") final String connectionInitSql

    ) {

        HikariDataSource hikariDataSource = new HikariDataSource(new HikariConfig() {{
            setDataSourceClassName(dataSourceClass);
            setJdbcUrl(jdbcUrl);
            addDataSourceProperty("url", jdbcUrl);

            setUsername(username);
            setPassword(password);
            setRegisterMbeans(true);

            setConnectionTimeout(connectionTimeout);
            setMinimumIdle(minimumIdle);
            setMaximumPoolSize(maximumPoolSize);
            setIdleTimeout(idleTimeout);
            setMaxLifetime(maxLifetime);
            setConnectionInitSql(connectionInitSql);

            setReadOnly(reauditOnly);
        }});

        return hikariDataSource;
    }

    @Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource, @Value("${hikaricp.fetchSize}") Integer fetchSize) {
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource, true);
        jdbcTemplate.setLazyInit(true);
        // 必须设置 autoCommit = false,否则 该设置不起作用
        jdbcTemplate.setFetchSize(fetchSize);
        // jdbcTemplate.setMaxRows(50000);  // 最多返回的结果行数 ,太大会导致 OOM
        // jdbcTemplate.setQueryTimeout(120);  // 查询数据库的最大时间
        /**
         * 仅对 call 存过的返回值起作用 ,Map 的大小写不区分
         */
        jdbcTemplate.setResultsMapCaseInsensitive(true);

        jdbcTemplate.afterPropertiesSet();
        return jdbcTemplate;
    }

    @Bean
    public PlatformTransactionManager yourManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
}

DaoImpl.class 就是对 jdbcTemplate的简单封装,太简单不需展示

classpath:jdbc.properties 是一些常用的 数据库配置,参考如下 :

oracle.jdbc.driverClass=oracle.jdbc.OracleDriver # 单个数据源
oracle.jdbc.dataSourceClass=oracle.jdbc.pool.OracleDataSource // 数据库连接池配置需要 
#=================================================================

oracle.jdbc.url=jdbc:oracle:thin:@IP:PORT:servicename
oracle.jdbc.username=
oracle.jdbc.password=

# HikariCP config
# 是否自动提交事务,默认true
hikaricp.autoCommit=true
# 从连接池中获取可用连接的最长等待时间 2 min,超时会抛异常 SQLException 。最小 250 ms,Default: 30000 (30 seconds)
hikaricp.connectionTimeout=120000
# 允许连接处于空闲的最长时间,超时会被断开(一般是 该参数 +15s后断开,最长 +30s)。但是当池中连接数小于 minimumIdle 时,此参数不生效。 0 代表用不断开,最小 10000ms (10 seconds). Default: 600000 (10 minutes)
hikaricp.idleTimeout=300000
# 池中连接的最大生存期。正在使用中的连接永远也不会断开。强烈建议设置改参数,而且最好比数据库本身的时长限制短上几秒钟。0 表示无限生存期,当然,这取决于idleTimeout设置。默认值:1800000(30分钟)
hikaricp.maxLifetime=1800000
# 仅针对 缺少API Connection.isValid() 的老旧驱动 ,如果您的驱动程序支持JDBC4,我们强烈建议不要设置此属性。作用是 在连接池返回连接之前先测试连接是否可用。hikari 会自动检测是否兼容 JDBC4的API,并会有明确的日志报错。
#hikaricp.connectionTestQuery=SELECT * FROM DUAL
# 允许 处于空闲状态的连接的最大个数,hikari会自动补充货源,保证这个数字。为了保证最佳响应和峰值性能,最好不要设置该参数,默认 与 maximumPoolSize 一样
#hikaricp.minimumIdle=10
# 最大连接数,包括空闲和使用中的。当使用中的连接数达到该值后,再次调用 getConnection() 会被阻塞,最长等待 connectionTimeout 后超时。 默认是10
# 最佳连接数的计算公式 connections = ((cpu_core * 2) + effective_spindle_count)  ,如果是SSD,effective_spindle_count = 0,参考 https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing
hikaricp.minimumIdle=5
hikaricp.maximumPoolSize=15
hikaricp.readOnly=false
# 放入连接池之前,先检测该sql是否正常,如果此SQL无效或抛出异常,则 会触发标准的重试逻辑
hikaricp.connectionInitSql=SELECT 1 FROM DUAL
# 单次TCP 连接返回的结果数 
hikaricp.fetchSize=200

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值