• Spring3 (事务管理)


    简介: 1、事务管理。2、整合Junit。3、整和Web

    1       事务管理

    1.1   回顾事务

    l  事务:一组业务操作ABCD,要么全部成功,要么全部不成功。

    l  特性:ACID

           原子性:整体

           一致性:完成

           隔离性:并发

           持久性:结果

    l  隔离问题:

           脏读:一个事务读到另一个事务没有提交的数据

           不可重复读:一个事务读到另一个事务已提交的数据(update)

           虚读(幻读):一个事务读到另一个事务已提交的数据(insert)

    l  隔离级别:

           read uncommitted:读未提交。存在3个问题

           read committed:读已提交。解决脏读,存在2个问题

           repeatable read:可重复读。解决:脏读、不可重复读,存在1个问题。

           serializable       :串行化。都解决,单事务。

          

    l  mysql 事务操作--Savepoint 

     1 需求:AB(必须),CD(可选)
     2 
     3 Connection conn = null;
     4 
     5 Savepoint savepoint = null;  //保存点,记录操作的当前位置,之后可以回滚到指定的位置。(可以回滚一部分)
     6 
     7 try{
     8 
     9   //1 获得连接
    10 
    11   conn = ...;
    12 
    13   //2 开启事务
    14 
    15   conn.setAutoCommit(false);
    16 
    17   A
    18 
    19   B
    20 
    21   savepoint = conn.setSavepoint();
    22 
    23   C
    24 
    25   D
    26 
    27   //3 提交事务
    28 
    29   conn.commit();
    30 
    31 } catche(){
    32 
    33   if(savepoint != null){   //CD异常
    34 
    35      // 回滚到CD之前
    36 
    37      conn.rollback(savepoint);
    38 
    39      // 提交AB
    40 
    41      conn.commit();
    42 
    43   } else{   //AB异常
    44 
    45      // 回滚AB
    46 
    47      conn.rollback();
    48 
    49   }
    50 
    51 }
    事物操作伪代码演示

     

    1.2   事务管理介绍

    1.2.1   导入jar包

    transaction  -->spring-tx-3.2.0.RELEASE 

     

    1.2.2   三个顶级接口

    1、 PlatformTransactionManager  平台事务管理器,spring要管理事务,必须使用事务管理器

           进行事务配置时,必须配置事务管理器

    2、 TransactionDefinition:事务详情(事务定义、事务属性),spring用于确定事务具体详情,

           例如:隔离级别、是否只读、超时时间 等

           进行事务配置时,必须配置详情。spring将配置项封装到该对象实例。

    3、 TransactionStatus:事务状态,spring用于记录当前事务运行状态。例如:是否有保存点,事务是否完成。

           spring底层根据状态进行相应操作。

    1.2.3   PlatformTransactionManager  事务管理器

    l  导入jar包:需要时平台事务管理器的实现类

          

    l  常见的事务管理器

           DataSourceTransactionManager  ,jdbc开发时事务管理器,采用JdbcTemplate

           HibernateTransactionManager,hibernate开发时事务管理器,整合hibernate

     

    l  api详解

    TransactionStatus getTransaction(TransactionDefinition definition) ,事务管理器 通过“事务详情”,

                    获得“事务状态”,从而管理事务。

    void commit(TransactionStatus status)  根据状态提交

    void rollback(TransactionStatus status) 根据状态回滚

    1.2.4   TransactionStatus

     

    1.2.5   TransactionDefinition

     

    l  传播行为:在两个业务之间如何共享事务。

    PROPAGATION_REQUIRED , required , 必须  【默认值】

           支持当前事务,A如果有事务,B将使用该事务。

           如果A没有事务,B将创建一个新的事务。

    PROPAGATION_SUPPORTS ,supports ,支持

           支持当前事务,A如果有事务,B将使用该事务。

           如果A没有事务,B将以非事务执行。

    PROPAGATION_MANDATORY,mandatory ,强制

           支持当前事务,A如果有事务,B将使用该事务。

           如果A没有事务,B将抛异常。

    PROPAGATION_REQUIRES_NEW , requires_new ,必须新的

           如果A有事务,将A的事务挂起,B创建一个新的事务

           如果A没有事务,B创建一个新的事务

    PROPAGATION_NOT_SUPPORTED ,not_supported ,不支持

           如果A有事务,将A的事务挂起,B将以非事务执行

           如果A没有事务,B将以非事务执行

    PROPAGATION_NEVER ,never,从不

           如果A有事务,B将抛异常

           如果A没有事务,B将以非事务执行

    PROPAGATION_NESTED ,nested ,嵌套

           A和B底层采用保存点机制,形成嵌套事务。

    掌握:PROPAGATION_REQUIRED、PROPAGATION_REQUIRES_NEW、PROPAGATION_NESTED

    1.3   案例:转账

    1.3.1   搭建环境

    1.3.1.1         创建表

    create database ee19_spring_day03;
    
    use ee19_spring_day03;
    
    create table account(
    
      id int primary key auto_increment,
    
      username varchar(50),
    
      money int
    
    );
    
    insert into account(username,money) values('jack','10000');
    
    insert into account(username,money) values('rose','10000');
    表格Sql代码

    1.3.1.2         导入jar包

    l  核心:4+1

    l  aop : 4 (aop联盟、spring aop、aspectj规范、spring aspect)

    l  数据库:2  (jdbc/tx)

    l  驱动:mysql

    l  连接池:c3p0

     

    1.3.1.3         dao层

     1 public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {
     2 
     3  
     4 
     5    @Override
     6 
     7    public void out(String outer, Integer money) {
     8 
     9       this.getJdbcTemplate().update("update account set money = money - ? where username = ?", money,outer);
    10 
    11    }
    12 
    13  
    14 
    15    @Override
    16 
    17    public void in(String inner, Integer money) {
    18 
    19       this.getJdbcTemplate().update("update account set money = money + ? where username = ?", money,inner);
    20 
    21    }
    22 
    23  
    24 
    25 }
    Dao

     

    1.3.1.4         service层

     1 public class AccountServiceImpl implements AccountService {
     2 
     3  
     4 
     5    private AccountDao accountDao;
     6 
     7    public void setAccountDao(AccountDao accountDao) {
     8 
     9       this.accountDao = accountDao;
    10 
    11    }
    12 
    13    @Override
    14 
    15    public void transfer(String outer, String inner, Integer money) {
    16 
    17       accountDao.out(outer, money);
    18 
    19       //断电
    20 
    21 //    int i = 1/0;
    22 
    23       accountDao.in(inner, money);
    24 
    25    }
    26 
    27  
    28 
    29 }
    service

     

    1.3.1.5         spring配置

    <!-- 1 datasource -->
    
        <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    
            <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
    
            <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/ee19_spring_day03"></property>
    
            <property name="user" value="root"></property>
    
            <property name="password" value="1234"></property>
    
        </bean>
    
    
        <!-- 2 dao  -->
    
        <bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl">
    
            <property name="dataSource" ref="dataSource"></property>
    
        </bean>
    
        <!-- 3 service -->
    
        <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
    
            <property name="accountDao" ref="accountDao"></property>
    
        </bean>
    applicationContext.xml

     

    1.3.1.6         测试

     1   @Test
     2 
     3     public void demo01(){
     4 
     5         String xmlPath = "applicationContext.xml";
     6 
     7         ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
     8 
     9         AccountService accountService =  (AccountService) applicationContext.getBean("accountService");
    10 
    11         accountService.transfer("jack", "rose", 1000);
    12 
    13     }
    Test

     

    1.3.2   手动管理事务(了解)

    l  spring底层使用 TransactionTemplate 事务模板进行操作。

    l  操作

    1.service 需要获得 TransactionTemplate

    2.spring 配置模板,并注入给service

    3.模板需要注入事务管理器

    4.配置事务管理器:DataSourceTransactionManager ,需要注入DataSource

    1.3.2.1         修改service

     1 //需要spring注入模板
     2 
     3     private TransactionTemplate transactionTemplate;
     4 
     5     public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
     6 
     7         this.transactionTemplate = transactionTemplate;
     8 
     9     }
    10 
    11     @Override
    12 
    13     public void transfer(final String outer,final String inner,final Integer money) {
    14 
    15         transactionTemplate.execute(new TransactionCallbackWithoutResult() {
    16 
    17 
    18             @Override
    19 
    20             protected void doInTransactionWithoutResult(TransactionStatus arg0) {
    21 
    22                 accountDao.out(outer, money);
    23 
    24                 //断电
    25 
    26 //              int i = 1/0;
    27 
    28                 accountDao.in(inner, money);
    29 
    30             }
    31 
    32         });
    33 
    34     }
    Service2

     

    1.3.2.2         修改spring配置

     1 <!-- 3 service -->
     2 
     3     <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
     4 
     5         <property name="accountDao" ref="accountDao"></property>
     6 
     7         <property name="transactionTemplate" ref="transactionTemplate"></property>
     8 
     9     </bean>
    10 
    11    
    12 
    13     <!-- 4 创建模板 -->
    14 
    15     <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
    16 
    17         <property name="transactionManager" ref="txManager"></property>
    18 
    19     </bean>
    20 
    21    
    22 
    23     <!-- 5 配置事务管理器 ,管理器需要事务,事务从Connection获得,连接从连接池DataSource获得 -->
    24 
    25     <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    26 
    27         <property name="dataSource" ref="dataSource"></property>
    28 
    29     </bean>
    applicationContext.xml

      

    1.3.3   工厂bean 生成代理:半自动

    l  spring提供 管理事务的代理工厂bean TransactionProxyFactoryBean

    1.getBean() 获得代理对象

    2.spring 配置一个代理

    1.3.3.1         spring配置

     1 <!-- 4 service 代理对象 
     2         4.1 proxyInterfaces 接口 
     3         4.2 target 目标类
     4         4.3 transactionManager 事务管理器
     5         4.4 transactionAttributes 事务属性(事务详情)
     6             prop.key :确定哪些方法使用当前事务配置
     7             prop.text:用于配置事务详情
     8                 格式:PROPAGATION,ISOLATION,readOnly,-Exception,+Exception
     9                     传播行为        隔离级别    是否只读        异常回滚        异常提交
    10                 例如:
    11                     <prop key="transfer">PROPAGATION_REQUIRED,ISOLATION_DEFAULT</prop> 默认传播行为,和隔离级别
    12                     <prop key="transfer">PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly</prop> 只读
    13                     <prop key="transfer">PROPAGATION_REQUIRED,ISOLATION_DEFAULT,+java.lang.ArithmeticException</prop>  有异常扔提交
    14     -->
    15     <bean id="proxyAccountService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    16         <property name="proxyInterfaces" value="com.itheima.service.AccountService"></property>
    17         <property name="target" ref="accountService"></property>
    18         <property name="transactionManager" ref="txManager"></property>
    19         <property name="transactionAttributes">
    20             <props>
    21                 <prop key="transfer">PROPAGATION_REQUIRED,ISOLATION_DEFAULT</prop>
    22             </props>
    23         </property>
    24     </bean>
    25 
    26     <!-- 5 事务管理器 -->
    27     <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    28         <property name="dataSource" ref="dataSource"></property>
    29     </bean>
    ApplicationContext.xml

    1.3.3.2         测试

     

    1.3.4   AOP 配置基于xml【掌握】

    l  在spring xml 配置aop 自动生成代理,进行事务的管理

    1.配置管理器

    2.配置事务详情

    3.配置aop

     (使用上一个笔记的aop编程实现)

     1 <!-- 4 事务管理 -->
     2 
     3     <!-- 4.1 事务管理器 -->
     4 
     5     <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
     6 
     7         <property name="dataSource" ref="dataSource"></property>
     8 
     9     </bean>
    10 
    11     <!-- 4.2 事务详情(事务通知)  , 在aop筛选基础上,对ABC三个确定使用什么样的事务。例如:AC读写、B只读 等
    12 
    13         <tx:attributes> 用于配置事务详情(属性属性)
    14 
    15             <tx:method name=""/> 详情具体配置
    16 
    17                 propagation 传播行为 , REQUIRED:必须;REQUIRES_NEW:必须是新的
    18 
    19                 isolation 隔离级别
    20 
    21     -->
    22 
    23     <tx:advice id="txAdvice" transaction-manager="txManager">
    24 
    25         <tx:attributes>
    26 
    27             <tx:method name="transfer" propagation="REQUIRED" isolation="DEFAULT"/>
    28 
    29         </tx:attributes>
    30 
    31     </tx:advice>
    32 
    33     <!-- 4.3 AOP编程,目标类有ABCD(4个连接点),切入点表达式 确定增强的连接器,从而获得切入点:ABC -->
    34 
    35     <aop:config>
    36 
    37         <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.itheima.service..*.*(..))"/>
    38 
    39     </aop:config>
    applicationContext.xml

      

    1.3.5   AOP配置基于注解【掌握】

    l  1.配置事务管理器,将并事务管理器交予spring

    l  2.在目标类或目标方法添加注解即可 @Transactional

    1.3.5.1         spring配置

     1 <!-- 4 事务管理 -->
     2     <!-- 4.1 事务管理器 -->
     3     <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
     4         <property name="dataSource" ref="dataSource"></property>
     5     </bean>
     6     <!-- 4.2 将管理器交予spring 
     7         * transaction-manager 配置事务管理器
     8         * proxy-target-class
     9             true : 底层强制使用cglib 代理
    10     -->
    11     <tx:annotation-driven transaction-manager="txManager"/>
    applicationContext.xml

    1.3.5.2         service 层

    @Transactional
    
    public class AccountServiceImpl implements AccountService {

    1.3.5.3         事务详情配置

     

    @Transactional(propagation=Propagation.REQUIRED , isolation = Isolation.DEFAULT)
    public class AccountServiceImpl implements AccountService {

     

    2       整合Junit

    l  导入jar包

           基本 :4+1

           测试:spring-test...jar

    1.让Junit通知spring加载配置文件

    2.让spring容器自动进行注入

    l  修改测试类

     1 @RunWith(SpringJUnit4ClassRunner.class)
     2 
     3 @ContextConfiguration(locations="classpath:applicationContext.xml")
     4 
     5 public class TestApp {
     6 
     7    
     8 
     9     @Autowired  //与junit整合,不需要在spring xml配置扫描
    10 
    11     private AccountService accountService;
    12 
    13    
    14 
    15     @Test
    16 
    17     public void demo01(){
    18 
    19 //      String xmlPath = "applicationContext.xml";
    20 
    21 //      ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
    22 
    23 //      AccountService accountService =  (AccountService) applicationContext.getBean("accountService");
    24 
    25         accountService.transfer("jack", "rose", 1000);
    26 
    27     }
    28 
    29  
    30 
    31 }
    Test

     

    3       整合web

    0.导入jar包

           spring-web.xml

          

    1.tomcat启动加载配置文件

           servlet --> init(ServletConfig) --> <load-on-startup>2

           filter --> init(FilterConfig)  --> web.xml注册过滤器自动调用初始化

           listener --> ServletContextListener --> servletContext对象监听【】

           spring提供监听器 ContextLoaderListener  --> web.xml  <listener><listener-class>....

                  如果只配置监听器,默认加载xml位置:/WEB-INF/applicationContext.xml

                 

    2.确定配置文件位置,通过系统初始化参数

           ServletContext 初始化参数 web.xml 

                  <context-param>

                         <param-name>contextConfigLocation

                         <param-value>classpath:applicationContext.xml

     1 <!-- 确定配置文件位置 -->
     2   <context-param>
     3       <param-name>contextConfigLocation</param-name>
     4       <param-value>classpath:applicationContext.xml</param-value>
     5   </context-param>
     6   
     7   <!-- 配置spring 监听器,加载xml配置文件 -->
     8   <listener>
     9       <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    10   </listener>
    Web.xml

     

    3.从servletContext作用域 获得spring容器 (了解)

    1 // 从application作用域(ServletContext)获得spring容器
    2         //方式1: 手动从作用域获取
    3         ApplicationContext applicationContext = 
    4                 (ApplicationContext) this.getServletContext().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
    5         //方式2:通过工具获取
    6         ApplicationContext apppApplicationContext2 = 
    7                 WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());
    Servlet

      

  • 相关阅读:
    leetcode------Palindrome Number
    leetcode------Minimum Depth of Binary Tree
    leetcode------Binary Tree Level Order Traversal II
    leetcode------Plus One
    leetcode------Plus One
    leetcode------Min Stack
    leetcode------Binary Tree Level Order Traversal
    递归树与非递归树的不同实现【转载,个人感觉写的比较好的一篇,值得去思考】
    leetcode------Compare Version Numbers
    leetcode------Majority Element
  • 原文地址:https://www.cnblogs.com/soficircle/p/7113425.html
Copyright © 2020-2023  润新知