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. 只读事务 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);
    }
}因为设置了事务只读,所以不能执行代码中的插入操作

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还是提交成功了


// 模拟异常
        if(1 == 1){
           throw new RuntimeException();
        }
事务发生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);
    }和明显事务没有回滚,数据提交成功

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();
        }
    }

在AccountServiceImpl的transfer方法中模拟异常
// 模拟异常
        String s = null;
        s.toString();

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










