事务的概念
事务:是数据库操作最基本单位,逻辑上的一组操作,要么都成功,如果有一个失败所有操作都失败。
事务的四大特性:
使用代码开启事务的过程(一共分为4步):
- public void accountMoney(){
- try {
- //1.手动开启事务
- //2.编写业务逻辑
- // userDao.addMoney();
- // userDao.reduceMoney();
- //3.没有发生异常,提交事务
- } catch (Exception e) {
- //4.发生异常,事务回滚
- e.printStackTrace();
- }
- }
在JavaEE的开发中主要包含三层结构:controller层(web层)、service层(业务层)、dao层,一般事务添加到业务层(service层)上。
在spring进行事务的管理主要分为两种方式:编程式事务管理和声明式事务管理,一般常用的是声明式事务管理,下面将介绍声明式事务管理。
声明式事务管理有两种实现方式:
这篇博客主要讲解三大部分:①基于xml配置文件和注解的混合方式,②基于完全xml配置文件的方式,③基于完全注解的方式
在Spring进行事务声明式事务管理,底层使用的AOP。
目录
提供接口PlatformTransactionManager ,接口 PlatformTransactionManage 代表事务管理器,这个接口针对不同的框架提供不同的实现类 (接口 PlatformTransactionManager),其中在spring中以及Mybatis中使用的都是 实现类DataSourceTransactionManager,而Hibernate中使用的是实现类HibernateTransactionManager
在依赖引入的时候,要注意每个以来版本之间是否会有冲突,即有没有兼容的问题,不兼容的话,会爆上一篇博客的错误。地址:Error creating bean with name ‘userService‘ defined in file [D:\ajavaproject\coding\atguiguLearnSpri_网恋褙骗八万的博客-CSDN博客
- "1.0" encoding="UTF-8"?>
- <project xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <packaging>warpackaging>
-
- <parent>
- <artifactId>atguiguLearnSpring5artifactId>
- <groupId>org.examplegroupId>
- <version>1.0-SNAPSHOTversion>
- parent>
- <modelVersion>4.0.0modelVersion>
-
- <artifactId>Spring5_demo6artifactId>
-
- <dependencies>
- <dependency>
- <groupId>com.alibabagroupId>
- <artifactId>druidartifactId>
- <version>1.1.10version>
- dependency>
- <dependency>
- <groupId>mysqlgroupId>
- <artifactId>mysql-connector-javaartifactId>
- <version>5.1.6version>
- dependency>
- <dependency>
- <groupId>org.springframeworkgroupId>
- <artifactId>spring-aopartifactId>
- <version>5.0.2.RELEASEversion>
- dependency>
- <dependency>
- <groupId>org.springframeworkgroupId>
- <artifactId>spring-contextartifactId>
- <version>5.0.2.RELEASEversion>
- dependency>
- <dependency>
- <groupId>org.springframeworkgroupId>
- <artifactId>spring-txartifactId>
- <version>5.0.2.RELEASEversion>
- dependency>
- <dependency>
- <groupId>org.springframeworkgroupId>
- <artifactId>spring-coreartifactId>
- <version>5.0.2.RELEASEversion>
- dependency>
- <dependency>
- <groupId>org.springframeworkgroupId>
- <artifactId>spring-jdbcartifactId>
- <version>5.0.2.RELEASEversion>
- dependency>
- <dependency>
- <groupId>org.springframeworkgroupId>
- <artifactId>spring-ormartifactId>
- <version>5.0.2.RELEASEversion>
- dependency>
- <dependency>
- <groupId>org.springframeworkgroupId>
- <artifactId>spring-aspectsartifactId>
- <version>5.0.2.RELEASEversion>
- dependency>
- <dependency>
- <groupId>junitgroupId>
- <artifactId>junitartifactId>
- <version>4.12version>
- <scope>compilescope>
- dependency>
- dependencies>
-
-
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.pluginsgroupId>
- <artifactId>maven-compiler-pluginartifactId>
- <version>3.1version>
- <configuration>
- <source>1.8source>
- <target>1.8target>
- configuration>
- plugin>
- plugins>
- build>
-
-
- project>
- "1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:tx="http://www.springframework.org/schema/tx"
- xmlns:context="http://www.springframework.org/schema/context"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
- http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
- http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
-
-
- <context:component-scan base-package="com.atguigu.spring5">context:component-scan>
-
-
- <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
- destroy-method="close">
- <property name="url" value="jdbc:mysql:///user_db?useUnicode=true&characterEncoding=utf8"/>
- <property name="username" value="root"/>
- <property name="password" value="123456"/>
- <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
- bean>
-
-
- <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
-
- <property name="dataSource" ref="dataSource"/>
- bean>
-
-
- <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
-
- <property name="dataSource" ref="dataSource"/>
- bean>
-
-
- <tx:annotation-driven transaction-manager="transactionManager">tx:annotation-driven>
-
-
- beans>
@Transactional注解可以加到类上面,也可以把注解添加都方法上面。
加到类上面说明这个类的所有方法都添加事务,加到方法上面说明为当前的方法添加事务。
service类代码(为了验证事务注解有用性,在执行过程中放置一个除数为0的操作,会抛出异常)
- package com.atguigu.spring5.service;
-
- import com.atguigu.spring5.dao.UserDao;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Service;
- import org.springframework.transaction.annotation.Transactional;
-
-
- /**
- * @Author 不要有情绪的 ljy
- * @Date 2022/9/22 13:51
- * @Description:
- */
- @Service
- @Transactional
- public class UserService {
-
-
- @Autowired
- private UserDao userDao;
-
- public void accountMoney() {
-
- // try {
- // //1.开启事务
- // //2.编写业务逻辑
- userDao.addMoney();
- int i = 10 / 0;
- userDao.reduceMoney();
- // //3.没有发生异常,提交事务
- // } catch (Exception e) {
- // //4.发生异常,事务回滚
- // e.printStackTrace();
- // }
- }
- }
dao层代码
- package com.atguigu.spring5.dao;
-
- /**
- * @Author 不要有情绪的 ljy
- * @Date 2022/9/22 13:50
- * @Description:
- */
- public interface UserDao {
-
- //增加钱的功能
- public void addMoney();
-
- //减少钱的功能
- public void reduceMoney();
-
- }
dao的实现类daoImpl代码
- package com.atguigu.spring5.dao;
-
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.jdbc.core.JdbcTemplate;
- import org.springframework.stereotype.Repository;
-
- /**
- * @Author 不要有情绪的 ljy
- * @Date 2022/9/22 13:50
- * @Description:
- */
-
- @Repository
- public class UserDaoImpl implements UserDao {
- @Autowired
- private JdbcTemplate jdbcTemplate;
-
- @Override
- public void addMoney() {
- String sql = "update t_account set money = money + ? where id = ?";
- Object[] args = new Object[]{100,1};
- int update = jdbcTemplate.update(sql, args);
- System.out.println("钱增加成功!" + update);
- }
-
- @Override
- public void reduceMoney() {
- String sql = "update t_account set money = money - ? where id = ?";
- Object[] args = new Object[]{100, 2};
- int update = jdbcTemplate.update(sql, args);
- System.out.println("钱减少成功!" + update);
- }
- }
- package com.atguigu.spring5.test;
-
- import com.atguigu.spring5.service.UserService;
- import org.junit.Test;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
-
- /**
- * @Author 不要有情绪的 ljy
- * @Date 2022/9/23 9:29
- * @Description:
- */
- public class TestAccount {
-
- @Test
- public void test(){
- ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
- UserService userService = context.getBean("userService", UserService.class);
- userService.accountMoney();
- }
-
- }
由于触发了异常导致,整个过程没有全部执行完,因此事务发生了回滚,数据库中的数据没有发生改变。
依赖和1.2中的依赖一致,不再写出
配置文件相较于1.3有点不同,其主要分为以下部分:
- "1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:tx="http://www.springframework.org/schema/tx"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xmlns:context="http://www.springframework.org/schema/context"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
- http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
- http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
-
-
- <context:component-scan base-package="com.atguigu.spring5">context:component-scan>
-
-
- <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
- destroy-method="close">
- <property name="url" value="jdbc:mysql:///user_db?useUnicode=true&characterEncoding=utf8"/>
- <property name="username" value="root"/>
- <property name="password" value="123456"/>
- <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
- bean>
-
-
- <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
-
- <property name="dataSource" ref="dataSource"/>
- bean>
-
-
- <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
-
- <property name="dataSource" ref="dataSource"/>
- bean>
-
-
- <tx:advice id="txadvice">
-
- <tx:attributes>
-
- <tx:method name="accountMoney" propagation="REQUIRED"/>
-
-
- tx:attributes>
- tx:advice>
-
-
- <aop:config>
-
- <aop:pointcut id="pt" expression="execution(* com.atguigu.spring5.service.UserService.*(..))"/>
-
- <aop:advisor advice-ref="txadvice" pointcut-ref="pt"/>
- aop:config>
-
-
- beans>
逻辑代码和1.4章节差不多,只是要删除@Transactional注解
- package com.atguigu.spring5.service;
-
- import com.atguigu.spring5.dao.UserDao;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Service;
- import org.springframework.transaction.annotation.Transactional;
-
-
- /**
- * @Author 不要有情绪的 ljy
- * @Date 2022/9/22 13:51
- * @Description:
- */
- @Service
- //@Transactional
- public class UserService {
- @Autowired
- private UserDao userDao;
-
- public void accountMoney() {
-
- // try {
- // //1.开启事务
- // //2.编写业务逻辑
- userDao.addMoney();
- int i = 10 / 0;
- userDao.reduceMoney();
- // //3.没有发生异常,提交事务
- // } catch (Exception e) {
- // //4.发生异常,事务回滚
- // e.printStackTrace();
- // }
- }
- }
- @Test
- public void test2(){
- ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
- UserService userService = context.getBean("userService", UserService.class);
- userService.accountMoney();
- }
与1.6章节一致
这儿不再叙说,与前面的章节一致
此类的编写是为了代替xml配置文件,并且在该类上添加@Configuration注解,即告诉Spring容器该类是配置类。
- package com.atguigu.spring5.config;
-
- 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.stereotype.Component;
- import org.springframework.transaction.annotation.EnableTransactionManagement;
-
- /**
- * @Author 不要有情绪的 ljy
- * @Date 2022/9/29 21:53
- * @Description:
- */
- @Configuration //配置类
- @ComponentScan(basePackages = {"com.atguigu.spring5"}) //开启注解包扫描
- @EnableTransactionManagement //开启事务
- public class TestConfig {
- //创建数据库连接池
- @Bean
- public DruidDataSource getDruidDataSource() {
- DruidDataSource druidDataSource = new DruidDataSource();
- druidDataSource.setDriverClassName("com.mysql.jdbc.Driver");
- druidDataSource.setUrl("jdbc:mysql:///user_db?useUnicode=true&characterEncoding=utf8");
- druidDataSource.setUsername("root");
- druidDataSource.setPassword("123456");
- return druidDataSource;
- }
-
- //创建JdbcTemplate对象
- @Bean
- public JdbcTemplate getJdbcTemplate(DruidDataSource dataSource) {
- JdbcTemplate jdbcTemplate = new JdbcTemplate();
- jdbcTemplate.setDataSource(dataSource);
- return jdbcTemplate;
- }
-
- //创建事务管理器
- @Bean
- public DataSourceTransactionManager getDataSourceTransactionManager(DruidDataSource dataSource) {
- DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
- dataSourceTransactionManager.setDataSource(dataSource);
- return dataSourceTransactionManager;
- }
- }
与前面的一致,不再描述,但是记得添加上@Transactional注解
由于当前的配置类代替了xml配置为文件,因此测试方法在加载时候有一些变化,此时加载的应该为配置类。
- @Test
- public void test3(){
- ApplicationContext context = new AnnotationConfigApplicationContext(TestConfig.class);
- UserService userService = context.getBean("userService", UserService.class);
- userService.accountMoney();
- }
测试得到的结果与前面一致。
本博客主要讲解了三种spring管理事务的方式,每种方式原理都是一样的,要么使用注解的方式,要么配置文件的方式。整体而言使用注解方式较简单,建议在实际的开发过程中使用注解的方式,简便快速。
学习之所以会想睡觉,是因为那是梦开始的地方。
ଘ(੭ˊᵕˋ)੭ (开心) ଘ(੭ˊᵕˋ)੭ (开心)ଘ(੭ˊᵕˋ)੭ (开心)ଘ(੭ˊᵕˋ)੭ (开心)ଘ(੭ˊᵕˋ)੭ (开心)
------不写代码不会凸的小刘