当前位置: 首页 > 图灵资讯 > 技术篇> 事务的属性2

事务的属性2

来源:图灵教育
时间:2023-06-15 09:28:26

1.事务超时130

代码如下

@Transactional(timeout = 10)

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

如果事务中所有DML语句都没有在10秒以上执行,最终结果将选择回滚。

默认值-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_bc

2.只读事务131

代码如下:

@Transactional(readOnly = true)

将当前事务设置为只读事务,只允许select语句在事务执行过程中执行,deleteinsertupdate不能执行。

这一特点的作用是:启动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_事务的属性_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_Source_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 // 开启事务注释publicic class Spring6Config {    // 看到这个@Bean注释后,Spring框架,这种标记的方法将被调用,    // 该方法的返回值为java对象,将自动纳入物联网容器管理。    // 返回的对象是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_事务的属性_08

在Accountserviceimpl的transfer方法中模拟异常

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

事务的属性2_spring_09

事务的属性2_bc_10

钱不少说明事务起作用。