声明式事务
JdbcTemplate
JdbcTemplate配置
依赖
spring-orm会把jdbc和tx引入
tx指的是事务管理
<dependencies> <!-- 基于Maven依赖传递性,导入spring-context依赖即可导入当前所需所有jar包 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.3.1</version> </dependency> <!-- Spring 持久化层支持jar包 --> <!-- Spring 在执行持久化层操作、与持久化层技术进行整合过程中,需要使用orm、jdbc、tx三个 jar包 --> <!-- 导入 orm 包就可以通过 Maven 的依赖传递性把其他两个也导入 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>5.3.1</version> </dependency> <!-- Spring 测试相关 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.3.1</version> </dependency> <!-- junit测试 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!-- MySQL驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.16</version> </dependency> <!-- 数据源 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.0.31</version> </dependency> </dependencies>
配置IOC
<!-- 导入外部属性文件 --> <context:property-placeholder location="classpath:jdbc.properties"/> <!-- 配置数据源 --> <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="url" value="${atguigu.url}"/> <property name="driverClassName" value="${atguigu.driver}"/> <property name="username" value="${atguigu.username}"/> <property name="password" value="${atguigu.password}"/> </bean> <!-- 配置 JdbcTemplate --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <!-- 装配数据源 --> <property name="dataSource" ref="druidDataSource"/> </bean>
仍然是需要写context:property-placeholder来获取properties文件,其中的classpath指通过类路径获取,web项目中必须指定
然后通过${}的方式进行属性获取
然后将配置好的数据源放入JdbcTemplate中
Spring整合JUnit测试
通过两个注解可以使测试类在spring的测试环境中运行
然后就可以省去手动获取ioc容器的过程,使用自动注入来获取对象
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:spring-jdbc.xml") public class JDBCTemplateTest { @Autowired private JdbcTemplate jdbcTemplate; }
声明式事务概念
编程式事务
写死的事务,通过trycatchfinally写
声明式事务
使用切面,将事务代码抽取出来
spring中有封装好的,只需要在配置文件中配置开启,然后在需要事务管理的方法上写一个注解@Transactional就可以了
@Transactional也可以修饰类,类中全部的方法都会被事务管理
开启事务的注解驱动
需要在IOC文件中配置标签,一定要配置spring-tx的那个
<tx:annotation-driven transaction-manager="transactionManager">
然后还需要配置事务管理器
声明式事务的属性
只读
当事务中的操作不涉及修改,只查询数据时才可以设置,会让数据库进行某些优化
@Transactional(readOnly=true)
超时
当设定的时间内,事务没有执行完,会强制回滚并抛出异常。单位为秒
@Transactional(timeout=3)
回滚策略
设置什么情况回滚,什么情况不回滚
默认情况下任何运行时异常都会回滚,所以一般只需要设置noRollBack不会滚的情况
rollBackFor
rollBackForClassName
noRollBackFor后面写类.class
noRollBackForClassName后面写"全类名"
这四个里面写的都是异常类
事务隔离级别
一共四种
读未提交
事务1可以读取到事务2没提交的数据
读已提交
事务1只能读取到事务2提交完的数据
可重复度
事务每次读取同一个数据都会返回相同的结果
当事务1对某条数据进行操作时会进行加锁,其他事务无法对其进行操作
但当其他事务添加数据后,事务1仍可以读取到新的数据,会出现幻读情况
mysql比较特殊
mysql的可重复读级别解决了幻读问题,而且mysql的默认隔离级别是可重复度级别
串行化
事务对表进行操作是串联的,一个事务执行完毕下一个事务才可以开始执行
每个事务对表操作时都会对当前表进行加锁
其中Oracle只支持读已提交和串行化,默认为读已提交
mysql四种都支持,默认为可重复度
设置方法
@Transactional(isolation=Isolation.DEFAULT)
@Transactional(isolation=Isolation.READ_UNCOMMITTED)
@Transactional(isolation=Isolation.READ_COMMITTED)
@Transactional(isolation=Isolation.READ_REPEATABLE_READ)
@Transactional(isolation=Isolation.SERIALIZABLE)
事务的传播行为
@Transactional(propagation=Propagation.REQUIRED)default外部可以传进来
@Transactional(propagation=Propagation.REQUIRES_NEW)开启新事物,相当于一个子事务
当一个事务调用另一个事务时,默认会使用外层的事务统一管理,但可以propagation属性设置为REQUIRES_NEW,就可以开启子事务,其他地方回滚不会影响子事务内部操作,子事务回滚也只会回滚到子事务开启时的状态。
基于XML的声明式事务
需要在IOC容器配置文件中进行配置
先配置tx:advice,配置id,并使用之前的事务管理器,将事务管理配置成通知
然后使用aop:config进行事务的切入点的配置,使用<aop:advisor>标签为通知进行切入点配置
在tx:advice中,可以配置属性,使用tx:attributes中的tx:method为每个特定的函数进行事务详细属性的配置,也可以使用正则表达式进行匹配。
<aop:config>
<!-- 配置事务通知和切入点表达式 --> <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.atguigu.spring.tx.xml.service.impl.*.*(..))">
</aop:advisor> </aop:config>
<!-- tx:advice标签:配置事务通知 -->
<!-- id属性:给事务通知标签设置唯一标识,便于引用 -->
<!-- transaction-manager属性:关联事务管理器 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes>
<!-- tx:method标签:配置具体的事务方法 -->
<!-- name属性:指定方法名,可以使用星号代表多个字符 --> <tx:method name="get*" read-only="true"/> <tx:method name="query*" read-only="true"/> <tx:method name="find*" read-only="true"/>
<!-- read-only属性:设置只读属性 -->
<!-- rollback-for属性:设置回滚的异常 -->
<!-- no-rollback-for属性:设置不回滚的异常 -->
<!-- isolation属性:设置事务的隔离级别 -->
<!-- timeout属性:设置事务的超时属性 -->
<!-- propagation属性:设置事务的传播行为 --> <tx:method name="save*" read-only="false" rollback- for="java.lang.Exception" propagation="REQUIRES_NEW"/> <tx:method name="update*" read-only="false" rollback- for="java.lang.Exception" propagation="REQUIRES_NEW"/> <tx:method name="delete*" read-only="false" rollback- for="java.lang.Exception" propagation="REQUIRES_NEW"/> </tx:attributes> </tx:advice>
目前用过的所有依赖总结
spring-aspects切面,并且会代入aspectJ编织者weaver,基于XML方式的声明式事务需要这个
浙公网安备 33010602011771号