Spring入门(五)---- Spring中的事务控制

五、Spring中的事务控制

  • 为什么需要事务?

事务是对一系列的数据库操作(比如插入多条数据)进行统一的提交或回滚操作,如果插入成功,那么一起成功,如果中间有一条出现异常,那么回滚之前的所有操作,这样可以防止在脏数据,方式数据库出现问题。

  • 事务的四个特性(ACID)
  • 原子性(Atomicity):事务是一个原子操作,由一系列动作组成。事务的原子性确保动作要么全部完成,要么完全不起作用。
  • 一致性(Consistency):一旦事务完成(成功或失败),系统必须确保它建模的业务处于一致状态,而不会是部分消失部分失败,在现实中的数据不应该被破坏。
  • 隔离性(Isolation):可能有许多事务处理相同的数据,因此每个事务应该与其它事务隔离起来,防止数据损坏。
  • 持久性(Durability):一旦事务完成,无论发生什么系统错误,它的结果都不应该受到影响。

1、Spring中事务的核心接口

在这里插入图片描述
**Spring并不直接管理事务,而是提供了多种事务管理器,**Spring事务管理器的接接口是org.springframework.transaction.PlatformTransactionManager,通过这个接口,Spring为各个平台如JDBC、Hibernate等都提供了对应的事务管理器,但是具体的实现就是各个平台自己的事情了。

1.1PlatformTransactionManager

getTransaction:获取事务状态信息

commit:提交事务

rollback:回滚事务

1.2TransactionDefinition

  • String getName():获取事务的名称
  • int getIssolationLevel():获取事务的隔离级别

ISOLATION_DEFAULT: 使用后端数据库默认的隔离级别,Mysql 默认采用的

ISOLATION_READ_UNCOMMITTED: 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。

ISOLATION_READ_COMMITTED: 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生。

ISOLATION_REPEATABLE_READ: 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。

ISOLATION_SERIALIZABLE: 最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。

  • int getPropagationBehavior():获取事务的传播行为

PROPAGATION_REQUIRED: 如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务.

PROPAGATION_SUPPORTS: 如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。

PROPAGATION_MANDATORY: 如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。(mandatory:强制性)

PROPAGATION_REQUIRES_NEW: 创建一个新的事务,如果当前存在事务,则把当前事务挂起。

TransactionDefinition.PROPAGATION_NOT_SUPPORTED: 以非事务方式运行,如果当前存在事务,则把当前事务挂起。

PROPAGATION_NEVER: 以非事务方式运行,如果当前存在事务,则抛出异常

  • int getTimeout():获取事务的超时时间
  • boolean isReadOnly():获取事务是否只读

1.3TransactionStatus

描述了某个时间点上事务对象的状态信息,包含6个具体的操作

viod flush():刷新事务

boolean hasSavePoint():获取是否存在存储点

boolean isCompleted:获取事务是否已经完成

booean isNewTransaction:获取事务是否为新的事务

boolean isRollbackOnly:获取事务是否回滚

void setRollbackOnly:设置事务回滚

2、基于xml的事务控制

 <!-- 配置业务层-->
    <bean id="accountService" class="com.simon.service.impl.AccountServiceImpl">
        <property name="accountDao" ref="accountDao"></property>
    </bean>

    <!-- 配置账户的持久层-->
    <bean id="accountDao" class="com.simon.dao.impl.AccountDaoImpl">
        <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://localhost:3306/spring?characterEncoding=utf8&amp;serverTimezone=UTC"></property>
        <property name="username" value="root"></property>
        <property name="password" value="root"></property>
    </bean>
    <!-- spring中基于XML的声明式事务控制配置步骤
        1、配置事务管理器
        2、配置事务的通知
                此时我们需要导入事务的约束 tx名称空间和约束,同时也需要aop的
                使用tx:advice标签配置事务通知
                    属性:
                        id:给事务通知起一个唯一标识
                        transaction-manager:给事务通知提供一个事务管理器引用
        3、配置AOP中的通用切入点表达式
        4、建立事务通知和切入点表达式的对应关系
        5、配置事务的属性
               是在事务的通知tx:advice标签的内部

     -->
    <!-- 配置事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!-- 配置事务的通知-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <!-- 配置事务的属性
              isolation:用于指定事务的隔离级别。默认值是DEFAULT,表示使用数据库的默认隔离级别。
              propagation:用于指定事务的传播行为。默认值是REQUIRED,表示一定会有事务,增删改的选择。查询方法可以选择SUPPORTS。
              read-only:用于指定事务是否只读。只有查询方法才能设置为true。默认值是false,表示读写。
              timeout:用于指定事务的超时时间,默认值是-1,表示永不超时。如果指定了数值,以秒为单位。
              rollback-for:用于指定一个异常,当产生该异常时,事务回滚,产生其他异常时,事务不回滚。没有默认值。表示任何异常都回滚。
              no-rollback-for:用于指定一个异常,当产生该异常时,事务不回滚,产生其他异常时事务回滚。没有默认值。表示任何异常都回滚。
      -->
        <tx:attributes>
            <!--method中的那么表示接入点方法,可以使用通配符-->
            <tx:method name="*" propagation="REQUIRED" read-only="false"/>
            <tx:method name="find*" propagation="SUPPORTS" read-only="true"></tx:method>
        </tx:attributes>
    </tx:advice>

    <!-- 配置aop-->
    <aop:config>
        <!-- 配置切入点表达式-->
        <aop:pointcut id="pt1" expression="execution(* com.simon.service.impl.*.*(..))"></aop:pointcut>
        <!--建立切入点表达式和事务通知的对应关系 -->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pt1"></aop:advisor>
    </aop:config>

3、基于注解的事务配置

<!-- 配置spring创建容器时要扫描的包-->
    <context:component-scan base-package="com.itheima"></context:component-scan>

    <!-- 配置JdbcTemplate-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <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://localhost:3306/eesy"></property>
        <property name="username" value="root"></property>
        <property name="password" value="1234"></property>
    </bean>

    <!-- spring中基于注解 的声明式事务控制配置步骤
        1、配置事务管理器
        2、开启spring对注解事务的支持
        3、在需要事务支持的地方使用@Transactional注解
     -->
    <!-- 配置事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!-- 开启spring对注解事务的支持-->
    <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>

4、基于纯注解的事务配置

  • 注解(容器类)–父类

    /**
     * spring的配置类,相当于bean.xml
     */
    @Configuration //表明是一个配置类
    @ComponentScan("com.simon")
    @Import({JdbcConfig.class,TransactionConfig.class}) //导入两个配置子类
    @PropertySource("jdbcConfig.properties") //数据源配置文件
    @EnableTransactionManagement  //开启事务
    public class SpringConfiguration {
    }
    
  • 和数据库连接相关的配置类—Jdbc.config

    /**
     * 和连接数据库相关的配置类
     */
    public class JdbcConfig {
    
        @Value("${jdbc.driver}")
        private String driver;
    
        @Value("${jdbc.url}")
        private String url;
    
        @Value("${jdbc.username}")
        private String username;
    
        @Value("${jdbc.password}")
        private String password;
    
        /**
         * 创建JdbcTemplate
         * @param dataSource
         * @return
         */
        @Bean(name="jdbcTemplate")
        public JdbcTemplate createJdbcTemplate(DataSource dataSource){
            return new JdbcTemplate(dataSource);
        }
    
        /**
         * 创建数据源对象
         * @return
         */
        @Bean(name="dataSource")
        public DataSource createDataSource(){
            DriverManagerDataSource ds = new DriverManagerDataSource();
            ds.setDriverClassName(driver);
            ds.setUrl(url);
            ds.setUsername(username);
            ds.setPassword(password);
            return ds;
        }
    }
    
  • 和事务管理器配置相关的配置类—TransactionConfig

    /**
     * 和事务相关的配置类
     */
    public class TransactionConfig {
    
        /**
         * 用于创建事务管理器对象
         * @param dataSource
         * @return
         */
        @Bean(name="transactionManager")
        public PlatformTransactionManager createTransactionManager(DataSource dataSource){
            return new DataSourceTransactionManager(dataSource);
        }
    }
    
    • 数据源配置文件—jdbcConfig.properties

      jdbc.driver=com.mysql.jdbc.Driver
      jdbc.url=jdbc:mysql://localhost:3306/spring
      jdbc.username=root
      jdbc.password=root
      

发布了77 篇原创文章 · 获赞 42 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/dreame_life/article/details/104496311