zoukankan      html  css  js  c++  java
  • Spring事务管理

    -------------------siwuxie095

       

       

       

       

       

       

       

       

    Spring 事务管理

       

       

    (一)事务的相关概念

       

       

    1、什么是事务

       

    事务是逻辑上的一组操作,构成这组操作的各个逻辑单元,

    要么一起成功,要么一起失败

       

       

       

       

    2、事务特性(简称 ACID

       

    1原子性:强调事务的不可分割

       

    2一致性:事务执行前后,数据的完整性保持一致

       

    3隔离性:一个事务在执行的过程中,不应该受到其他事务的干扰

       

    4持久性:事务一旦结束,数据就持久到数据库

       

       

       

       

    3、如果不考虑隔离性引发安全性问题

       

    1脏读

       

    一个事务读到了另一个事务未提交的数据

       

       

    2不可重复读

       

    一个事务读到了另一个事务已经提交的 update 的数据,导致多次查询结果不一致

       

       

    3幻读(也称 虚读

       

    一个事务读到了另一个事务已经提交的 insert 的数据,导致多次查询结果不一致

       

       

       

       

    4、解决读问题:设置事务隔离级别

       

    1未提交读:脏读、不可重复读、幻读都有可能发生

       

    2已提交读:避免脏读,但不可重复读和幻读有可能发生

       

    3可重复读:避免脏读和不可重复读,但幻读有可能发生

       

    4可串行化:避免以上所有读问题

       

       

       

       

       

       

       

    (二)Spring 事务管理 API

       

       

    1、Spring 事务管理有两种方式

       

    1编程式事务管理:手动编写代码实现事务管理

       

       

    2声明式事务管理:通过一段配置实现事务管理(建议)

       

    1)基于 XML 的方式

       

    2)基于注解的方式

       

       

       

       

    2、Spring 事务管理 API 介绍

       

    1)接口:PlatformTransactionManager(事务管理器)

       

    Spring 为不同的持久层框架提供了 PlatformTransactionManager 接口的不同实现类

       

    ORM 持久层框架

    实现类

    Spring JDBC

    DataSourceTransactionManager

    iBatis

    DataSourceTransactionManager

    MyBatis

    DataSourceTransactionManager

    Hibernate

    HibernateTransactionManager

    JPA

    JpaTransactionManager

    JDO

    JdoTransactionManager

    JTA

    JtaTransactionManager

       

       

       

    2)接口:TransactionDefinition(事务定义)

       

    用来定义事务相关属性,给事务管理器使用

       

    1)隔离级别

       

    2)传播行为

       

    3)超时信息

       

    4)是否只读

       

       

       

    3)接口:TransactionStatus(事务状态)

       

    事务运行过程中,记录每个时间点的事务状态信息

       

       

       

    事务管理器根据事务定义的信息进行事务的管理,在此过程中

    会产生一些状态,将事务状态记录下来

       

       

       

       

       

       

       

    (三)测试:以转账为例

       

       

    1、在 MySQL 中手动创建数据库和表

       

    数据库名:tx_db,表名:account,字段:id、name、money

       

       

       

    手动添加数据,用作测试

       

       

       

       

       

    2、具体实现

       

    1)编写一个 Dao 类

       

    AccountDao.java:

       

    package com.siwuxie095.dao;

       

    import org.springframework.jdbc.core.JdbcTemplate;

       

    public class AccountDao {

       

    private JdbcTemplate jdbcTemplate;

     

    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {

    this.jdbcTemplate = jdbcTemplate;

    }

     

    public void lessMoney(String from, int money) {

    String sql="update account set money=money-? where name=?";

    jdbcTemplate.update(sql, money, from);

    }

     

    public void moreMoney(String to, int money) {

    String sql="update account set money=money+? where name=?";

    jdbcTemplate.update(sql, money, to);

    }

     

    }

       

       

       

    2)编写一个 Service 类

       

    AccountService.java:

       

    package com.siwuxie095.service;

       

    import com.siwuxie095.dao.AccountDao;

       

    public class AccountService {

       

    private AccountDao accountDao;

     

    public void setAccountDao(AccountDao accountDao) {

    this.accountDao = accountDao;

    }

     

    public void transfer(String from,String to,int money) {

    accountDao.lessMoney(from, money);

    accountDao.moreMoney(to, money);

    }

     

    }

       

       

       

    3)在配置文件中进行配置

       

    applicationContext.xml:

       

    <?xml version="1.0" encoding="UTF-8"?>

    <beans xmlns="http://www.springframework.org/schema/beans"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xmlns:aop="http://www.springframework.org/schema/aop"

    xmlns:context="http://www.springframework.org/schema/context"

    xmlns:tx="http://www.springframework.org/schema/tx"

    xsi:schemaLocation="

    http://www.springframework.org/schema/beans

    http://www.springframework.org/schema/beans/spring-beans.xsd

    http://www.springframework.org/schema/aop

    http://www.springframework.org/schema/aop/spring-aop.xsd

    http://www.springframework.org/schema/context

    http://www.springframework.org/schema/context/spring-context.xsd

    http://www.springframework.org/schema/tx

    http://www.springframework.org/schema/tx/spring-tx.xsd">

     

     

    <!-- 配置内置连接池 -->

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">

    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>

    <!--

    jdbc:mysql:///tx_db jdbc:mysql://localhost:3306/tx_db 的简写

    -->

    <property name="url" value="jdbc:mysql:///tx_db"/>

    <property name="username" value="root"/>

    <property name="password" value="8888"/>

    </bean>

     

     

    <!-- 配置对象并注入属性 -->

    <bean id="accountService" class="com.siwuxie095.service.AccountService">

    <property name="accountDao" ref="accountDao"></property>

    </bean>

     

    <bean id="accountDao" class="com.siwuxie095.dao.AccountDao">

    <property name="jdbcTemplate" ref="jdbcTemplate"></property>

    </bean>

     

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">

    <!-- JdbcTemplate 源代码中有属性 dataSource 和其 set 方法,所以可以注入 -->

    <property name="dataSource" ref="dataSource"></property>

    </bean>

       

       

    </beans>

       

       

       

    4)编写一个测试类

       

    TestDemo.java:

       

    package com.siwuxie095.test;

       

    import org.junit.Test;

    import org.springframework.context.ApplicationContext;

    import org.springframework.context.support.ClassPathXmlApplicationContext;

       

    import com.siwuxie095.service.AccountService;

       

    public class TestDmo {

       

    /**

    * 手动加上 @Test 以进行单元测试(将自动导入 JUnit 4 jar 包)

    *

    * 选中方法名,右键->Run As->JUint Test

    */

    @Test

    public void testService() {

     

    ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");

     

    AccountService accountService=(AccountService) context.getBean("accountService");

     

    accountService.transfer("小白", "小黑", 1000);

    }

     

    }

       

       

       

       

    3、问题所在

       

    上面的程序虽然可以正常运行,并实现转账功能,但如果在一个人

    转出钱时出现异常,另一个人就不会收到钱

       

    一个人少钱,另一个人却没有多钱,导致钱丢失了

       

       

       

       

    4、解决方法

       

    添加事务管理,当出现异常时进行回滚

       

       

       

       

       

       

       

       

       

    【made by siwuxie095】

  • 相关阅读:
    用户交互程序
    使用 fetch 封装网络请求,返回promise 对象
    我收藏的脚手架
    DOM API简析
    encodeURI、encodeURIComponent、decodeURI、decodeURIComponent的区别
    Flex 布局
    react 基础
    javaScript 设计模式
    js 之正则表达式
    如何使用RedisTemplate访问Redis数据结构
  • 原文地址:https://www.cnblogs.com/siwuxie095/p/7417314.html
Copyright © 2011-2022 走看看