0
点赞
收藏
分享

微信扫一扫

事务的属性2

1. 事务超时  130

代码如下

@Transactional(timeout = 10)

以上代码表示设置事务的超时时间为10秒。

表示超过10秒如果该事务中所有的DML语句还没有执行完毕的话,最终结果会选择回滚。

默认值-1,表示没有时间限制。

这里有个坑,事务的超时时间指的是哪段时间?

在当前事务当中,最后一条DML语句执行之前的时间。如果最后一条DML语句后面很有很多业务逻辑,这些业务代码执行的时间不被计入超时时间

package com.powernode.bank.service.impl;

import com.powernode.bank.dao.AccountDao;
import com.powernode.bank.pojo.Account;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;

/**
 * 事务的隔离级别   129
 * 测试事务隔离级别:READ_UNCOMMITTED 和 READ_COMMITTED
 **/
@Service("i2")
public class IsolationService2 {

    @Resource(name = "accountDao")
    private AccountDao accountDao;

    // 2号
    // 负责insert
    //@Transactional
    @Transactional(timeout = 10)// 设置事务超时时间为10秒。(这个时间记录的是你程序中执行的最后一条DML语句之前才会有效)
        public void save(Account act) throws IOException {

        // 睡眠一会
        try {
            Thread.sleep(1000 * 15);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        accountDao.insert(act);
    }
}

//测试事务超时  130
    @Test
    public void testIsolation2() throws IOException {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
        IsolationService2 i2 = applicationContext.getBean("i2", IsolationService2.class);
        Account act = new Account("act-004", 1000.0);
        i2.save(act);
    }

当然,如果想让整个方法的所有代码都计入超时时间的话,可以在方法最后一行添加一行无关紧要的DML语句。

事务的属性2_spring

2. 只读事务  131

代码如下:

@Transactional(readOnly = true)

将当前事务设置为只读事务,在该事务执行过程中只允许select语句执行,delete insert update均不可执行。

该特性的作用是:启动spring的优化策略。提高select语句执行效率。

如果该事务中确实没有增删改操作,建议设置为只读事务。

设置哪些异常回滚事务

代码如下:

package com.powernode.bank.service.impl;

import com.powernode.bank.dao.AccountDao;
import com.powernode.bank.pojo.Account;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;

/**
 * 事务的隔离级别   129
 * 测试事务隔离级别:READ_UNCOMMITTED 和 READ_COMMITTED
 **/
@Service("i2")
public class IsolationService2 {

    @Resource(name = "accountDao")
    private AccountDao accountDao;

    // 2号
    // 负责insert
    //@Transactional
    //@Transactional(timeout = 10)// 设置事务超时时间为10秒。(这个时间记录的是你程序中执行的最后一条DML语句之前才会有效)
    @Transactional(readOnly = true, timeout = 10) // 设置事务超时时间为10秒。
    public void save(Account act) throws IOException {

        // 睡眠一会
        /*try {
            Thread.sleep(1000 * 15);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }*/

        accountDao.insert(act);
    }

}

因为设置了事务只读,所以不能执行代码中的插入操作

事务的属性2_spring_02

4. 设置哪些异常回滚事务  132

表示只有发生RuntimeException异常或该异常的子类异常才回滚。

@Transactional(rollbackFor = RuntimeException.class)

// 模拟异常
        if(1 == 1){
            throw new IOException();
        }

测试

//测试事务异常  132
    @Test
    public void testIsolation2() throws IOException {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
        IsolationService2 i2 = applicationContext.getBean("i2", IsolationService2.class);
        Account act = new Account("act-004", 1000.0);
        i2.save(act);
    }

事务发生IOException异常

虽然发生异常但是事务没有回滚,数据act-004还是提交成功了

事务的属性2_spring_03

事务的属性2_bc_04

// 模拟异常
        if(1 == 1){
           throw new RuntimeException();
        }

事务的属性2_事务的属性_05

事务发生RuntimeException异常回滚,很明显数据没提交成功

5. 设置哪些异常不回滚事务  133

代码如下:

表示发生NullPointerException或该异常的子类异常不回滚,其他异常则回滚。

@Transactional(noRollbackFor = NullPointerException.class)

// 模拟异常
        if(1 == 1){
            throw new NullPointerException();
        }

测试

//测试事务异常  132
    @Test
    public void testIsolation2() throws IOException {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
        IsolationService2 i2 = applicationContext.getBean("i2", IsolationService2.class);
        Account act = new Account("act-004", 1000.0);
        i2.save(act);
    }

和明显事务没有回滚,数据提交成功

事务的属性2_事务的属性_06

6. 事务的全注解式开发   134

编写一个类来代替配置文件,代码如下:

package com.powernode.bank;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;

//事务的全注解开发   134
@Configuration // 代替spring.xml配置文件,在这个类当中完成配置。
@ComponentScan("com.powernode.bank") // 组件扫描
@EnableTransactionManagement // 开启事务注解
public class Spring6Config {

    // Spring框架,看到这个@Bean注解后,会调用这个被标注的方法,
    // 这个方法的返回值是一个java对象,这个java对象会自动纳入IoC容器管理。
    // 返回的对象就是Spring容器当中的一个Bean了。
    // 并且这个bean的名字是:dataSource
    @Bean(name = "dataSource")
    public DruidDataSource getDataSource(){
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/spring6");
        dataSource.setUsername("root");
        dataSource.setPassword("lzl");
        return dataSource;
    }

    @Bean(name = "jdbcTemplate")
    public JdbcTemplate getJdbcTemplate(DataSource dataSource){ //Spring在调用这个方法的时候会自动给我们传递过来一个dataSource对象。
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        jdbcTemplate.setDataSource(dataSource);
        return jdbcTemplate;
    }

    @Bean(name = "txManager")
    public DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource){
        DataSourceTransactionManager txManager = new DataSourceTransactionManager();
        txManager.setDataSource(dataSource);
        return txManager;
    }

}

//事务的全注解开发  134
    @Test
    public void testNoXML(){
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Spring6Config.class);
        AccountService accountService = applicationContext.getBean("accountService", AccountService.class);
        try {
            accountService.transfer("act-001", "act-002", 10000);
            System.out.println("转账成功");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

事务的属性2_spring_07

事务的属性2_spring_08

在AccountServiceImpl的transfer方法中模拟异常

// 模拟异常
        String s = null;
        s.toString();

事务的属性2_bc_09

事务的属性2_Source_10

钱也没少说明事务起作用了

举报

相关推荐

0 条评论