声明式事务

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">

然后还需要配置事务管理器
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <property name="dataSource" ref="dataSource"></property>
</bean>

 

声明式事务的属性

只读

当事务中的操作不涉及修改,只查询数据时才可以设置,会让数据库进行某些优化

@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方式的声明式事务需要这个