Spring-事务

面试题

事务是怎么处理的?
    事务是通过设置连接里面的非自动AutoCommit属性来处理的。设置事务为非自动提交。,默认是自动提交的。
1:事务的概念
    事务是一系列作为一个逻辑单元来执行的操作集合
    它是数据库维护数据一致性的单位,它将数据库从一个一致状态,转变为新的另外一个一致状态
    说的简单一点就是:如果一组处理步骤要么全部成功,要么全部失败,这样就保证了数据始终一直的状态
    维护了数据的完整和可靠性

2 :jdbc处理事务的逻辑 
    详见jdbc事务.png

3:事务的属性
    事务的4个属性:原子性、一致性、隔离性、持续性。这四个属性通常称为ACID特性。
    原子性(atomicity):一个事务是一个不可分割的工作单位,事务中包括的所有操作要么都做,要么都不做。
    一致性(consistency):事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
    隔离性(isolation):一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,
        并发执行的各个事务之间不能互相干扰。
    持久性(durability):持续性也称永久性(permanence),指一个事务一旦提交,
        它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。

4:事务的传播特性
    事务的传播特性指处于不同事物的方法在相互调用时,执行期间,事务的维护情况
    一般有两种方式:
    * PROPAGATION_REQUIED :如果存在一个事务,则支持当前事务,如果没有事务则开启。  
    * PROPAGATION_REQUIED_NEW :总是开启一个新事务。   

5:事务管理的类型
    事务管理分为两种类型,分为编程式事务和声明式事务
    编程式事务
        编程式事务管理可以清楚的定义事务的边界
        可以实现细粒度的事务控制,开发者可以通过程序代码来控制你的事务何时开始,何时结束,类似于jdbc事务.png
        但是事务的控制与业务代码耦合在一起,不能共用 ,而且开发效率低,不便于维护
    声明式事务
        声明式事务可以结合spring AOP的概念,只需要通过配置在指定的方法中加入事务控制.
        如果需要修改或者删除事务,移除配置即可,解除了系统服务(事务)与业务代码的耦合,而且方便管理
        在实际开发中,一般提倡用声明式事务管理     

6:spring跟事务的关系
    * 事务原本是数据库中的概念,是在dao层
        但是一般情况下,我们会把事务管理提升到我们的业务层(service)
        这是为了更好的是用事务来管理我们的业务逻辑
    * spring并不直接管理事务,而是提供了多种事务管理器
        根据不同的数据应用方式,(jdbc(自定义封装的jdbc,jdbctemplate,mybatis)/hibernate)提供了对应的事务管理器
        jdbc:DataSourceTransactionManager
        hibenate:HibernateTranactionManager
        所有的事务管理器实现了一个共同的接口
        org.springframework.transaction.PlatformTransactionManager  
        他提供了三个方法 commit rollback getTransaction(TransactionDefinition(用来定义事务的一系列属性))

7:Spring实现事务有三种方式
    * 基于xml配置
    * 注解
    * aspectJ           

8:模拟转账      

9: spring基于xml配置实现事务
    * 环境搭建:引入jar,引入aop约束
        aopalliance-1.0.jar
        spring-aop-4.2.1.RELEASE.jar
        spring-tx.jar
    * xml配置事务
        详见applicationContext.xml  AccountWithTransTest.java

10: spring注解方式实现事务
    在第九步的基础上引入tx约束 
    详见 applicationContext-annotation.xml
        AccountWithTransAnnoTest.Java

11: spring AspectJ实现事务

AccountDao

package com.tz.spring.sysmanage.dao.impl;

import org.springframework.jdbc.core.JdbcTemplate;

import com.tz.spring.sysmanage.dao.IAccountDao;

/**
 * 
 * @author Administrator
 *
 */
public class AccountDao implements IAccountDao{

    private JdbcTemplate jdbcTemplate;


    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }


    public boolean addAccountMoney(String account, double money) {
        boolean updateFlag = false;
        String updateSql = "UPDATE M_ACCOUNT SET AC_MONEY = AC_MONEY+? WHERE AC_NAME = ? ";
        int rows = this.jdbcTemplate.update(updateSql, money,account);
        if(rows>0){
            updateFlag = true;          
        }
        return updateFlag;

    }


    public boolean subAccountMoney(String account, double money) {
        boolean updateFlag = false;
        String updateSql = "UPDATE M_ACCOUNT SET AC_MONEY = AC_MONEY-? WHERE AC_NAME = ? ";
        int rows = this.jdbcTemplate.update(updateSql, money,account);
        if(rows>0){
            updateFlag = true;          
        }
        return updateFlag;
    }





}

AccountService

package com.tz.spring.sysmanage.service.impl;

import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.tz.spring.sysmanage.dao.IAccountDao;
import com.tz.spring.sysmanage.service.IAccountService;

/**
 * 
 * @author Administrator
 *
 */
public class AccountService implements IAccountService{

    private IAccountDao accountDao;

    public void setAccountDao(IAccountDao accountDao) {
        this.accountDao = accountDao;
    }


@Transactional(isolation=Isolation.DEFAULT,propagation=Propagation.REQUIRED )
public boolean operateAccount(String fromAccount, String toAccount ,double money) {
        //转账业务步骤
        //1:从转账人账户减去转账金额 
        //2:从被转账人账户增加转账金额
        System.out.println("---------------转账开始---------------");       
        accountDao.subAccountMoney(fromAccount, money);

        System.out.println("转账金额---------------"+money);

        int i= 1/0;

        accountDao.addAccountMoney(toAccount, money);               
        System.out.println("---------------转账结束---------------");

        return true;
    }
}

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:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop" 
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

   <bean id = "accountService" 
                class = "com.tz.spring.sysmanage.service.impl.AccountService">
        <property name="accountDao" ref = "accountDao"></property>      
   </bean>

   <!--注册studentDao  -->
   <bean id = "accountDao" 
                class = "com.tz.spring.sysmanage.dao.impl.AccountDao">
        <property name="jdbcTemplate" ref = "jdbcTemplate"></property> 
                </bean>

    <!--注册springjdbc查询模板 模板依赖数据源  -->
    <bean id= "jdbcTemplate" class = "org.springframework.jdbc.core.JdbcTemplate"> 
        <property name="dataSource" ref = "dataSource"></property>

    </bean>

    <context:property-placeholder location = "classpath:jdbc.properties"/>

    <bean id= "dataSource" 
            class= "com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driver}"></property>    
        <property name="jdbcUrl" value="${jdbc.url}"></property>       
        <property name="user" value="${jdbc.user}"></property>     
        <property name="password" value="${jdbc.password}"></property>                     
    </bean>

    <!--注册事务管理器  -->
    <bean id = "txMgr" class = "org.springframework.jdbc.datasource.DataSourceTransactionManager" > 
        <property name="dataSource" ref = "dataSource"></property>
    </bean>     

    <!--注册事务代理 -->
    <bean id= "transProxy" class= "org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
        <property name="transactionManager" ref= "txMgr"></property>
        <property name="target" ref = "accountService"></property>
        <property name="transactionAttributes">
            <props>
                <prop key="oper*">ISOLATION_DEFAULT,PROPAGATION_REQUIRED</prop>
            </props>
        </property>
    </bean>
</beans>         

applicationContext-annotation.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:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:aop="http://www.springframework.org/schema/aop" 
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.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      
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">


   <bean id = "accountService" 
                class = "com.tz.spring.sysmanage.service.impl.AccountService">
        <property name="accountDao" ref = "accountDao"></property>      
   </bean>


   <!--注册studentDao  -->
   <bean id = "accountDao" 
                class = "com.tz.spring.sysmanage.dao.impl.AccountDao">
        <property name="jdbcTemplate" ref = "jdbcTemplate"></property> 
                </bean>

    <!--注册springjdbc查询模板 模板依赖数据源  -->
    <bean id= "jdbcTemplate" class = "org.springframework.jdbc.core.JdbcTemplate"> 
        <property name="dataSource" ref = "dataSource"></property>

    </bean>


    <context:property-placeholder location = "classpath:jdbc.properties"/>

    <bean id= "dataSource" 
            class= "com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driver}"></property>    
        <property name="jdbcUrl" value="${jdbc.url}"></property>       
        <property name="user" value="${jdbc.user}"></property>     
        <property name="password" value="${jdbc.password}"></property>                     
    </bean>


    <!--注册事务管理器  -->
    <bean id = "txMgr" class = "org.springframework.jdbc.datasource.DataSourceTransactionManager" > 
        <property name="dataSource" ref = "dataSource"></property>
    </bean>     

    <!--开启事务的注解驱动  -->
    <tx:annotation-driven transaction-manager="txMgr"/> 

</beans>         

AccountWithTransAnnoTest

package com.tz.spring.sysmanage.test;

import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.tz.spring.sysmanage.service.IAccountService;

public class AccountWithTransAnnoTest {


    private  ApplicationContext ac = null;

    @Before
    public void init(){
        ac = new ClassPathXmlApplicationContext("applicationContext-annotation.xml");
    }


    @Test
    public void testOperatorAccount(){
        IAccountService accountService = (IAccountService)ac.getBean("accountService");
        accountService.operateAccount("李四", "张三", 100);
    }

}

applicationContext-aspectJ.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:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:aop="http://www.springframework.org/schema/aop" 
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans.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      
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">


   <bean id = "accountService" 
                class = "com.tz.spring.sysmanage.service.impl.AccountService">
        <property name="accountDao" ref = "accountDao"></property>      
   </bean>


   <!--注册studentDao  -->
   <bean id = "accountDao" 
                class = "com.tz.spring.sysmanage.dao.impl.AccountDao">
        <property name="jdbcTemplate" ref = "jdbcTemplate"></property> 
                </bean>

    <!--注册springjdbc查询模板 模板依赖数据源  -->
    <bean id= "jdbcTemplate" class = "org.springframework.jdbc.core.JdbcTemplate"> 
        <property name="dataSource" ref = "dataSource"></property>

    </bean>


    <context:property-placeholder location = "classpath:jdbc.properties"/>

    <bean id= "dataSource" 
            class= "com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driver}"></property>    
        <property name="jdbcUrl" value="${jdbc.url}"></property>       
        <property name="user" value="${jdbc.user}"></property>     
        <property name="password" value="${jdbc.password}"></property>                     
    </bean>


    <!--注册事务管理器  -->
    <bean id = "txMgr" class = "org.springframework.jdbc.datasource.DataSourceTransactionManager" > 
        <property name="dataSource" ref = "dataSource"></property>
    </bean>     

    <!--注册通知  -->
    <tx:advice id = "txAdvice" transaction-manager="txMgr">
        <tx:attributes>
            <tx:method name="oper*" isolation="DEFAULT" propagation="REQUIRED"/>        
        </tx:attributes>    
    </tx:advice>

    <!-- aop配置,切入点表达式和通知匹配 -->
    <aop:config>
        <aop:pointcut expression="execution(* *..AccountService.*(..))" id="accountPointCut"/>      
        <aop:advisor advice-ref="txAdvice" pointcut-ref="accountPointCut"/>
    </aop:config>

</beans>         

猜你喜欢

转载自blog.csdn.net/weixin_37243717/article/details/79934484