这里写目录标题
-
- 八.Spring事务管理
- 九.事务传播行为
- 十.Spring集成MyBatis
八.Spring事务管理
事务可以看作是对数据库若干操作组成的一个单元**(整体)**。我们在开发企业应用时,对于业务成员最常见的操作是对数据读写的多步操作的结合。由与数据库在顺序执行的过程中,任何一步都可能发生异常,异常会导致后续操作无法完成,此时由于业务逻辑并未正确的完成,之前的成功操作的数据并不可靠,需要在这种情况下进行回退。
事务的作用就是为了保证用户的每一个操作都是可靠的,事务的每一步操作都必须成功执行,只要有发生异常就回退到事务开始未进行操作的状态,这些操作要么都完成,要么都取消,从而保证数据满足一致性的要求。
这就是事务的原子性(不可分割性)
Spring中的事务分为两种形式,一种是编程式事务,一种是声明式事务
编程式事务:
? 在项目中很少使用,这种方式需要注入一个事务管理对象TransactionTemplate,然后在我们代码中需要提交事务或回滚事务时自己写代码实现。
声明式事务:
? 声明式事务管理建立在AOP基础上,本质是对方法前后进行拦截,所以声明式事务是方法级别的。
Spring声明事务管理方式由两种:
基于xml配置
基于注解实现
Spring 事物管理 APIPlatformTransactionManager 事物管理器接口 Spring 针对不同的 dao 框架,提供了不同的实现类,Jdbc,mybatis 事物管理实 现类是 DataSourceTransactionManager
配置步骤:
首先配置事务管理器 :
<!-- 配置 spring 事务管理类, 并注入数据源 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"></property>
</bean>
具体实现:
(1)基于xml配置(了解)
<!--配置spring事务传播行为, 这是spring框架自己特有的一个功能--><tx:advice id="txadvice" transaction-manager="transactionManager"><tx:attributes><tx:method name="save" propagation="REQUIRED"/></tx:attributes></tx:advice><!--配置事务管理--><aop:config><aop:pointcut id="save" expression="execution(* com.ffyc.spring.dao.UserDao.save())"/><aop:advisor advice-ref="txadvice" pointcut-ref="save"></aop:advisor></aop:config>
(2)注解方式配置【重要】
开启注解事务管理
<!-- 开启注解事务管理 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
控制事务:
在 service 中控制事务
@Service(value=“userservice”)
@Transactional**(propagation=Propagation.REQUIRED)(后面括号中的内容是事务传播行为的定义)**
九.事务传播行为
注:Spring事务传播行为,这是Spring框架自己特有的一种功能
什么叫事务传播行为?
既然是事务那么至少有两个东西才能发生传播。单体不存在传播这种行为。
事务传播行为(propagation behavior)指的就是当一个事务方法被另一个事务方法调用时,这个事务方法该如何进行。事务传播行为是Spring框架独有的事务增强特性,它不属于事务提供方数据库的行为。
例如:
methodA 事务方法调用 methodB 事务方法时,methodB 是继续在调 用者 methodA 的事务中运行呢,还是为自己开启一个新事务运行,这就是由 methodB 的事务传播行为决定的。
Spring定义了七种事务传播行为:
以下着重介绍三种事务传播行为:
- PROPAGATION_REQUIRED
指定的方法必须在当前事务内执行,若当前存在事务,加入到当前事务中,若当前没有事务,则创建一个新事务。也是Spring默认的传播行为。
Propagation.REQUIRED A方法传播行为REUIRQE 调用B方法 传播行为也是REQUIRED,那么B事务就加入到B事务中执行。 A方法无事务 调用B方法 B方法的传播行为也是REQUIRED,那么B方法会自己开启一个事务
2.PROPAGATION_SUPPORTS
支持当前事务,如果当前没有事务,就以非事务的方式执行。
Propagation.SUPPORTS A方法的传播行为为REUIRQE 调用B方法B方法的传播行为是SUPPORTS,那么B事务就加入到A事务中执行。A方法无事务 调用B方法,B方法的传播行为为SUPPORTS,那么B方法就以非事务的方法执行
3.PROPAGATION_REQUIRES_NEW
总是新建一个事务,如果当前存在事务把当前事务挂起,直到新建的事务结束。
A方法传播行为REUIRQE ,B方法传播行为REQUIRES_NEW,那么B方法会开启一个独立的新的事务执行,B不会受到A的影响。 A方法没有事务,B方法的事务的传播行为是REQUIRES_NEW,那么B方法会开启一个独立的新的事务执行
声明事务不生效的场景:
(1)@Transactional应用在非public修饰的方法上
(2)@Transactiona注解属性propagation设置错误
(3)同一个类中方法调用,导致@Transactional失效
(4)异常被catch捕获导致@Transactional失效
(5)数据库引擎不支持
十.Spring集成MyBatis
Spring集成MyBatis其核心是将SqlSeesionFactory交给Spring管理,并由Spring管理对dao接口的代理实现
步骤:
第一步导入相关jar包(注:我们是从Spring Helloworld 以及搭建好的情况下):
要多导入的
所有jar包在此:
<!--mybatis的jar包-->
<dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId> <version>3.4.2</version></dependency><!-- mysql的jar包--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.16</version></dependency><!--log4j的jar包--><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency><!-- 单元测试的jar包--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>provided</scope></dependency><!-- spring-context --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.2.RELEASE</version></dependency><!-- spring-aspects --><dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>5.2.2.RELEASE</version></dependency><!-- spring-jdbcs --><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.2.2.RELEASE</version></dependency><!--druid --><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.10</version></dependency><!-- mybatis-spring--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>1.3.1</version></dependency>
注:所用截图代码爆红的原因是用普通文件的格式打开的代码而不是java格式
第二步:在原有Spring项目配置的基础上配置mybatis
新加入的配置详解:
- log4j.properties:存放log4j配置信息的文件
- mybatis-config.xml:mybatis核心配置文件不过因为集成了spring有些配置已经被spring实现了所以要删掉一些属性和配置信息以免出错最后的配置是这样的:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--mybatis核心配置文件 -->
<configuration><!--全局配置--><settings><!--配置日志实现 使用log4j 添加log4j日志组件 导入jar包 配置属性文件--><setting name="logImpl" value="LOG4J"/><!--是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。--><setting name="mapUnderscoreToCamelCase" value="true"/><!--<setting name="lazyLoadingEnabled" value="true"/>--><!--lazyLoadTriggerMethods 指定哪些方法触发延迟加载--><setting name="lazyLoadTriggerMethods" value=""/><!--开启全局二级缓存配置--><setting name="cacheEnabled" value="true"/></settings><typeAliases><package name="com.ffyc.ssm.model"/> <!--配置相对应的具体实体的包一次性直接全部定义别名在mapper.xml中使用时就不用写全类名了--></typeAliases></configuration>
- spring_mybatis.xml:用spring来管理SqlSeesionFactory对象和接口代理对象的包
具体代码:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsd"><!-- spring管理生成SqlSessionFactory,读取mybatis各项配置配置--><bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="druidDataSource"></property><property name="configLocation" value="classpath:mybatis-config.xml"></property><property name="mapperLocations" value="classpath:mapper/*Mapper.xml"></property></bean><!--生成指定包下面的接口代理对象--><bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="basePackage" value="com.ffyc.ssm.dao"></property><property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property></bean>
</beans>
第三步:(在Spring上面加入mybatis的步骤)创建sql映射文件
第四步:在service层对根据需求对返回的数据做操作