【Spring5】数据库事务操作
Spring针对事务的操作
事务的概念:事务是数据库最基本的单元,逻辑上的一组操作,要么都成功,如果有一个操作失败则都失败。
事务的特性:ACID
原子性、一致性、隔离性、持久性
JavaEE环境三层结构
1.WEB视图层
2.Service业务逻辑层
主要包含一些业务逻辑
3.数据访问层
包含对数据库操作的方法,不涉及业务的操作
(1)事务添加到JavaEE三层结构的Service业务逻辑层
(2)在Spring进行事务管理操作,有两种方式:
①编程式事务管理:set autocommit = false
哪些操作会导致数据库的自动提交?
1.DDL操作一旦执行,都会自动提交,set autocommit = false对DDL操作无效。
2.DML默认情况会自动提交,可以通过set autocommit = false的方式取消DML操作的自动提交。
DML(Data Manipulation Language)数据操纵语言:
适用范围:对数据库中的数据进行一些简单操作,如insert,delete,update,select等.
DDL(Data Definition Language)数据定义语言:
适用范围:对数据库中的某些对象(例如,database,table)进行管理,如Create,Alter和Drop.
@Test public void updateTest() { Connection conn = null; try { conn = JDBCUtils.getConnection(); conn.setAutoCommit(false); // System.out.println(conn.getAutoCommit()); String sql1 = "update user set balance = balance - 100 where uer=?"; update(conn, sql1, "AA"); System.out.println(1/0); String sql2 = "update user set balance = balance + 100 where uer=?"; update(conn, sql2, "2B"); System.out.println("转账成功"); conn.commit(); } catch (SQLException throwables) { throwables.printStackTrace(); } finally { try { if(conn!=null) { conn.close(); } } catch (SQLException throwables) { throwables.printStackTrace(); } } }
②声明式事务管理
基于注解方式(使用)
1.创建事务管理器 DataSourceTractionManager,并注入数据源(数据库连接池)
<bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean>
2.在配置文件中引入名称空间tx
xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"
3.开启事务注解
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
4.在Service中添加事务注解@Tranctional
在类上面添加此注解,则类中所有方法都添加到事务,若添加到方法上,则此方法添加到事务。
@Transactional public void accountMoney(String id1, String id2, double money) { accountDao.reduceMoney(id1, money); System.out.println(1/0); accountDao.addMoney(id2, money); }
钱数不会发生变化
注解@Transactional的相关参数
1.propagation 事务传播行为
事务的传播行为,指的是多事务之间进行调用时,这个过程中的是如何管理的。

事务的传播行为由传播属性指定。Spring定义了7种传播行为,重点记住前两个。
传播属性 | 描述 |
---|---|
REQURED | 如果调用方法有事务在运行,当前方法就在这个事务中运行,否则,就启动一个自己的新的事务,并在此事务中运行。(如上图) |
REQURED_NEW | 当前方法必须启动自己的事务,并在自己的事务中进行,如果调用方法中有事务在运行,则应该将其挂起 |
SUPPORTS | |
NOT_SUPPORTED | |
MANDATORY | |
NEVER | |
NESTED |
@Transactional(propagation = Propagation.REQUIRED)
2.isolation 事务隔离级别
事务的隔离性,是指多事务之间操作不会受彼此影响,不考虑隔离性会产生很多问题:
①脏读:一个事务读取到了另一个未提交事务的数据(即两个事务都没有提交,事务可能回滚导致另一个事务读到脏数据)
②不可重复读:一个未提交事务读取到另一提交事务修改数据

未提交事务的事务两次读到的数据不一致,正常情况下是不能读取数据的
脏读是一个问题,但是不可重复读是一种现象,是允许发生的
③幻读:一个未提交事务读到另一个提交事务添加的数据,两次读到的行数不一致
通过设置事务隔离级别,解决读问题
脏读 | 不可重复读 | 幻读 | |
---|---|---|---|
Read Uncommitted (读未提交) |
有 | 有 | 有 |
Read Committed (读已提交) |
无 | 有 | 有 |
Repeatable Read (可重复读) |
无 | 无 | 有 |
Serializable (可串行化) |
无 | 无 | 无 |
@Transactional(isolation = Isolation.SERIALIZABLE)
MySQL默认级别为REPEATABLE READ可重复读
3.timeout 超时时间
事务需要在一定时间内进行提交,超过这个时间就会回滚
默认值为-1,表示不超时,值以s为单位
4.readOnly 是否只读
读:查询操作
写:添加修改删除操作
5.rollbackFor 事务回滚
设置出现哪些异常进行事务的回滚
6.noRollbackFor 事务不回滚
设置出现哪些异常不进行事务的回滚
只需设置为异常的Class即可
基于XML配置文件方式
(4)在Spring进行声明式事务管理,底层使用AOP原理
(5)Spring事务管理API
完全注解开发
@Configuration //配置类 @ComponentScan(basePackages = "com.hikaru") //扫描组件 @EnableTransactionManagement //开启事务 public class TxConfig { @Bean public DruidDataSource getDataSource() throws IOException { DruidDataSource druidDataSource = new DruidDataSource(); InputStream is = TxConfig.class.getClassLoader().getResourceAsStream("JDBC.properties"); Properties properties = new Properties(); properties.load(is); String driverClassName = properties.getProperty("driverClassName"); String url = properties.getProperty("url"); String username = properties.getProperty("username"); String password = properties.getProperty("password"); druidDataSource.setDriverClassName(driverClassName); druidDataSource.setUrl(url); druidDataSource.setUsername(username); druidDataSource.setPassword(password); return druidDataSource; } @Bean public DataSourceTransactionManager getTransactionManager(DruidDataSource dataSource) { DataSourceTransactionManager transactionManager = new DataSourceTransactionManager() ; transactionManager.setDataSource(dataSource); return transactionManager; } @Bean public JdbcTemplate getJdbcTemplate(DruidDataSource dataSource) { JdbcTemplate jdbcTemplate = new JdbcTemplate(); jdbcTemplate.setDataSource(dataSource); return jdbcTemplate; } @Test public void test() throws IOException, SQLException { DruidDataSource druidDataSource = getDataSource(); System.out.println(druidDataSource.getConnection()); } }
其中@Bean作用是将方法返回值注入IOC容器
配置类方法中的形参均在IOC容器中找到
测试
@Test public void test() { ApplicationContext context = new AnnotationConfigApplicationContext(TxConfig.class); AccountService accountService = context.getBean("accountService", AccountService.class); accountService.accountMoney("1001", "1002", 500); }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步