spring 声明式事务管理

spring 声明式事务管理

事务是我们在用 jdbc 操作数据库时,不可避免的问题。由于事务的执行。由于事务具有ACID 四大特性,执行起来还要受到事务的隔离级别,传播行为,锁机制等影响, 所以通过原生 jdbc 来控制事务面临着不少问题,同时通过原生 jdbc 控制事务也会带来大量代码冗余,如 conection.commit() 事务提交,conection.rollback() 事务回滚。spring 基于面向切面的编程思想,通过动态代理,方法增强,我们可以很轻松的通过配置和注解完成事务的管理。

spring声明式事务

Spring 声明式事务指的是,spring 为我们提供一套进行事务管理的API类。我们不需要进行过多的编码,只需要进行简单的xml或注解配置,就可以让spring 结题我们的事务管理的编码工作。我们做的事情就是配置,如何配置。

基于xml完成事务管理

基于 xml 配置声明式事务,主要还是集中在 spring 的配置文件。通过 IOC 和 AOP 共同完成声明式事务管理。

  1. 首先我们正常的在spring中配置好我们的持久层和服务层

    >   我们在进行事务管理一般都集中在 服务层,所以我们要先在 IOC 中配置好我们三成架构中原有的Bean 组件
    <!-- 配置 service --> 
    <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"> 
      <property name="accountDao" ref="accountDao"></property>
    </bean>
    <!-- 配置 dao --> 
    <bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl">
    <!-- 注入 dataSource --> 
      <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!-- 配置数据源 -->
    <bean id="dataSource"
    class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
      <property name="driverClassName" value="com.mysql.jdbc.Driver"> </property>
      <property name="url" value="jdbc:mysql:///spring_day04"></property> 
      <property name="username" value="root"></property> <property name="password" value="1234"></property>
    </bean>
  1. 在spring 中配置我们的事务管理器

    < bean id="transactionManger" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
      <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!-- 引用上面的事务管理 配置事务通知 -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
      <!--在 tx:advice 标签内部 配置事务的属性 --> 
    <!-- 
    name:指定方法名称,是业务核心方法,通过正则表达去对匹配到的服务层方法进行事务管理
    read-only:是否是只读事务。默认 false,不只读。
    isolation:指定事务的隔离级别。默认值是使用数据库的默认隔离级别。
    propagation:指定事务的传播行为。
    timeout:指定超时时间。默认值为:-1。永不超时。
    rollback-for:用于指定一个异常,当执行产生该异常时,事务回滚。产生其他异常,事务不回滚。
    没有默认值,任何异常都回滚。
    no-rollback-for:用于指定一个异常,当产生该异常时,事务不回滚,产生其他异常时,事务回
    滚。没有默认值,任何异常都回滚。
    -->
     <tx:attributes> 
      <tx:method name="*" read-only="false" propagation="REQUIRED"/>
      <tx:method name="find*" read-only="true" propagation="SUPPORTS"/>
     </tx:attributes>
    </tx:advice>
>   注意,我们通过配置了事务管理器及其属性,我们不再需要去过多的关注事务什么时候提交,事务在什么时候回滚。因为这些我们已经交由 spring 声明式事务去管理,这已经不是我们关注的中心,我们应该把重点转移到,需要通过 name的正则去匹配哪些方法进行事务管理,这个方法的事务需要我们去设计哪些属性,是否自读,事务隔离,事务传播,遇到什么时候进行事务回滚,事务超时时间。
  1. 配置AOP 实现spring 声明式事务管理

    <!--开启aop 配置 -->
    <aop:config>
      <!-- 配置切入点 --> 
    <aop:pointcut expression="execution(* com.stack.service.impl.*.*(..))" id="pt1"/>
      <!-- 引用事务通知类,完成事务管理,配置要对那些方法进行织入,组成切面 -->
      <aop:advisor advice-ref="txAdvice" pointcut-ref="pt1"/>
    </aop:config>
>   注意这里进行 aop 配置我们引用的是 aop:advisor 标签。这和我们配置切面的 aop:aspect 标签不一致,原因就在于我们自定义切面需要配置通知的位置,但是spring 事务管理,已经在内部帮我们配置好了,我们只需要引入事务通知即可。

基于注解完成事务管理

xml 开启注解支持(这里以 mybatis 为例)
<!-- 数据库相关的 IOC bean  在这里可以配置多数据源-->
    <!-- 1. 数据源 : DriverManagerDataSource  mybatis 在获取数据库连接需要 dataSource ,-->
    <bean id="dataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://182.92.221.190:3306/bookdb" />
        <property name="username" value="ldy" />
        <property name="password" value="135135ldy" />
    </bean>

    <!--
        2. mybatis的SqlSession的工厂: SqlSessionFactoryBean dataSource:引用数据源
        MyBatis定义数据源,同意加载配置
        通过 注入不同的数据源,实现多数据源的 sqlSessionFactory
    -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--
        3. mybatis自动扫描加载Sql映射文件/接口 : MapperScannerConfigurer sqlSessionFactory

        basePackage:指定sql映射文件/接口所在的包(自动扫描) sqlsession Builder
    -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.hyg.im.mapper"></property>
        <property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
    </bean>

    <!--
        4. 事务管理 : DataSourceTransactionManager dataSource:引用上面定义的数据源
        配置事务管理器
    -->
    <bean id="txManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!-- 5. 使用声明式事务
         transaction-manager:引用上面定义的事务管理器
         开启事务的注解配置
     -->
    <tx:annotation-driven transaction-manager="txManager" />

关键注解

@Transactional : 这个注解是spring 提供的事务管理的注解,这个注解可以出现在服务层类或者方法上。出现在类上,表明这个服务类都被spring 声明式事务管理。出现在方法上,表明对这个方法进行细粒度的事务配置。

/**
     * 在类上配置事务,在方法级别上详细配置事务,并可以指定事务的一些属性(只读,隔离性,传播行为:事务里面套着另一个事务,回滚机制)
     */
    @Transactional(readOnly = true,isolation = Isolation.REPEATABLE_READ,rollbackFor = Throwable.class)
纯注解配置

纯注解配置分为自己写配置类或者采用 spring Boot 方式

Spring Boot 方式
/**
 spring Boot 开启事务配置,只需要简单的配置一个注解 @EnableTransactionManagement 就能开启事务自动配置,具体事务管理就采用上面的@Transactional 主机就可以。
*/
@SpringBootApplication
@EnableTransactionManagement // 开启事务注解支持,相当于    <tx:annotation-driven transaction-manager="txManager" />
@MapperScan("com.stack.knowyouclient.dao") //配置 mybatis持久层扫描的包目录
public class KnowyouClientApplication {
    public static void main(String[] args) {
        SpringApplication.run(KnowyouClientApplication.class, args);
    }
}
spring 方式
/**
 * 配置事务管理器
 * @date 2019/11/7 15:41
 */
public class TransactionManager {
    @Bean(name = "transactionManager")
    public PlatformTransactionManager createTransactionManager(DataSource source){
        return new DataSourceTransactionManager(source);
    }
}
package config;

import org.springframework.context.annotation.*;
import org.springframework.transaction.annotation.EnableTransactionManagement;

/**
 * spring的配置类 相当于bean.xml
 * @date 2019/11/7 15:08
 */
@Configuration
@ComponentScan("com")  //扫描包
@Import({JdbcConfig.class,TransactionManager.class})
@PropertySource("jdbcConfig.properties")  //配置数据源
@EnableTransactionManagement   //开启事务注解支持     <tx:annotation-driven transaction-manager="txManager" />
public class SpringConfig {
}

补充说明,在 ssm 项目时,需要在应用的web.xml加载的 spring 的配置文件中,需要配置注解要扫描的包。

<!-- 加载Spring容器配置 -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <!-- 设置 Spring 容器加载所有的配置文件的路径 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath*:spring-*.xml</param-value>
    </context-param>

    <!-- 配置SpringMVC核心控制器 -->
    <servlet>
        <servlet-name>springMVC</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- 配置初始配置化文件,前面contextConfigLocation看情况二选一 -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath*:spring-mvc.xml</param-value>
        </init-param>
        <!-- 启动加载一次 -->
        <load-on-startup>1</load-on-startup>
    </servlet>
在spring MVC 配置文件中配置
<!-- IOC AOP注解持久层,服务层,控制层 扫描包目录(也可已在spring 配置文件中配置) -->
    <context:component-scan base-package="com.stack.im" />
    <!-- 开启 MVC 注解支持 @RequestMapping, @ ResponseBody -->
    <mvc:annotation-driven />
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值