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.只读事务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); }}
由于设置了只读事务,因此无法执行代码中的插入操作
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 // 开启事务注释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(); } }
在Accountserviceimpl的transfer方法中模拟异常
// 模拟异常 String s = null; s.toString();
钱不少说明事务起作用。