java-------------Spring 学习04

spring 事务管理


---------------------------------------------------------------------------------------------------------------------------------------
    
    Spring的事务管理(底层是AOP):
    
        一、概述:Spring事务管理高层抽象主要包括3个接口
                    
                    1、PlatformTransactionManager 事务管理器
                    
                    2、TransactionDefinition 事务定义信息(隔离、传播、超时、只读)
                    
                    3、TransactionStatus      事务具体运行状态
                    
                Spring为不同的持久化框架提供了不同PlatformTransactionManager接口实现
            
            
                2、TransactionDefinition 事务定义信息:
                
                    1、隔离级别:
                    
                                1、DEFAULT              使用后端数据库默认的隔离级别(spring中的的选择项)
                            
                                2、READ_UNCOMMITED(最差)      允许你读取还未提交的改变了的数据。可能导致脏、幻、不可重复读

                                3、READ_COMMITTED          允许在并发事务已经提交后读取。可防止脏读,但幻读和 不可重复读仍可发生
                                
                                (默认MYSQl和Order数据库使用3和4的隔离级别)        
                                
                                4、REPEATABLE_READ        对相同字段的多次读取是一致的,除非数据被事务本身改变。可防止脏、不可重复读,但幻读仍可能发生。

                                5、SERIALIZABLE    (最严格的,性能 差)        完全服从ACID的隔离级别,确保不发生脏、幻、不可重复读。这在所有的隔离级别中是最慢的,它是典型的通过完全锁定在事务中涉及的数据表来完成的


                        脏读:一个事务读取了另一个事务改写但还未提交的数据,如果这些数据被回滚,则读到的数据是无效的。
                        
                        不可重复读:在同一事务中,多次读取同一数据返回的结果有所不同。换句话说就是,后续读取可以读到另一事务已提交的更新数据。相反,“可重复读”在同一事务中多次读取数据时,能够保证所读数据一样,也就是,后续读取不能读到另一事务已提交的更新数据。
                        
                        幻读:一个事务读取了几行记录后,另一个事务插入一些记录,幻读就发生了。再后来的查询中,第一个事务就会发现有些原来没有的记录。
                    
                    2、传播行为:
                    
                                1、PROPAGATION_REQUIRED    支持当前事务,如果不存在 就新建一个----------》Spring默认使用
                                
                                2、PROPAGATION_SUPPORTS    支持当前事务,如果不存在,就不使用事务
                                
                                3、PROPAGATION_MANDATORY    支持当前事务,如果不存在,抛出异常
                                
                                4、PROPAGATION_REQUIRES_NEW    如果有事务存在,挂起当前事务,创建一个新的事务
                                
                                5、PROPAGATION_NOT_SUPPORTED    以非事务方式运行,如果有事务存在,挂起当前事务
                                
                                6、PROPAGATION_NEVER     以非事务方式运行,如果有事务存在,抛出异常
                                
                                7、PROPAGATION_NESTED    如果当前事务存在,则嵌套事务执行

                
                
            2、Spring的事务控制(Spring的声明式事务是通过AOP实现的IPO):
                
                    1、编程式事务控制:性能最好,最灵活,非常麻烦,在实际应用中很少使用,通过TransactionTemplate手动管理事务(高级工程师必备)

                    
                    2、声明式事务控制:
                    
                            1、原始型事务控制:
                            
                            2、基于Tx/AOP:(多数使用):
                            
                                    1、基于注解
                                    
                                    2、基于XML配置文件(代码侵入性最小)
                            
                        
                
            基于Spring事务案例:

                    
                    dao层:
                    
                                @Repository
                                public class UserDaoImpl implements UserDao {
                                    @Autowired
                                    private JdbcTemplate jdbcTemplate;

                                    @Override
                                    public void inmoney(String name, Integer money) {
                                        String sql = "update t_user set money=money+? where name=?";
                                        jdbcTemplate.update(sql, money, name);
                                    }

                                    @Override
                                    public void outmoney(String name, Integer money) {
                                        String sql = "update t_user set money=money-? where name=?";
                                        jdbcTemplate.update(sql, money, name);
                                    }
                                }
                
                    service层:
                    
                                @Service
                                public class UserServiceImpl implements UserService {
                                    @Autowired
                                    private UserDao userDao;
                                    @Override
                                    public void zhuangzhang() {
                                        userDao.outmoney("aa",10);
                                        int i=1/0;
                                        userDao.inmoney("bb",10);
                                    }
                                }

                
                    测试类:
                                
                                @Component
                                public class TestAdd {

                                    @Test
                                    public void say(){
                                        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("beans.xml");
                                        UserService userService=applicationContext.getBean(UserService.class);
                                        userService.zhuangzhang();
                                    }
                                }
                        
                    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"
                                       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/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
                                        http://www.springframework.org/schema/tx
                                        http://www.springframework.org/schema/tx/spring-tx.xsd">
                                    
                                    <!--Spring自动代理-->
                                    <context:annotation-config></context:annotation-config>
                                    
                                    <!--开启Spring扫描-->
                                    <context:component-scan base-package="com.zltz"></context:component-scan>
                                    
                                    <!--加载properties数据库信息文件-->
                                    <context:property-placeholder location="jdbc.properties"></context:property-placeholder>
                                    
                                    <!--获取dataSource数据源-->
                                    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
                                        <property name="url" value="${jdbc.url}"></property>
                                        <property name="password" value="${jdbc.password}"></property>
                                        <property name="driverClassName" value="${jdbc.driver}"></property>
                                        <property name="username" value="${jdbc.username}"></property>
                                    </bean>
                                    
                                    <!--添加dataSource数据源给对象-->
                                    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
                                        <property name="dataSource" ref="dataSource"></property>
                                    </bean>

                                    <!--定义事务管理 -->
                                    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
                                        <property name="dataSource" ref="dataSource"></property>
                                    </bean>
                                    
                                    <!--AOP相关信息 tx(增强)-->
                                    <tx:advice id="interceptor" transaction-manager="transactionManager">
                                        <tx:attributes>
                                        
                                            <!--事务的定义信息-->
                                            
                                            <tx:method name="zhuangzhang" propagation="REQUIRED"/>
                                            
                                            <tx:method>标签属性设置:
                                                            
                                                            0、name="zhuangzhang*":   进行事务控制的切入点的方法(对那个方法增强),如果有*号,比如说这个,就是在切入点中只要以zhuangzhang方法名开头的都进行事务控制。
                                                            
                                                            1、propagation="REQUIRED":传播行为
                                                            
                                                            2、isolation="DEFAULT":   隔离级别
                                                            
                                                            3、read-only="false":     是否只读
                                                            
                                                            4、rollback-for="Exception":默认就是Exception出现任何异常都回滚
                                                            
                                                            5、timeout="-1":           超时时间
                                                            
                                                            注意:此处的超时时间的设置-1为永不超时,面试时问,如果超时时间为30那么多少时间超时?答:永不超时,所以超时时间属性不管设置多少都是永不超时,默认写-1。
                                        </tx:attributes>
                                    </tx:advice>
                                    
                                    
                                    <aop:config>
                                        <!--切入点配置-->
                                        <aop:pointcut id="pois" expression="execution(* com.zltz.service..*(..))"></aop:pointcut>
                                        <aop:advisor advice-ref="interceptor" pointcut-ref="pois"></aop:advisor>
                                    </aop:config>
                                
                                </beans>
                
                
                    使用注解配置:
                        
                        xml中写入tx注解扫描:
                                
                                <tx:annotation-driven></tx:annotation-driven>
                                
                        在需要事务控制的方法上加注解:
                        
                            @Transactional注解
                            
                            
                            注意:在处理以上程序案例时以上代码没有错误,能跑通(毕竟比较简单),但是出错后数据库数据依旧修改,
                            
                                    起初怀疑是切面没有切入成功,但是数据库第一条SQL能修改数据第二条位执行说明已经切入了,
                                    
                                    就怀疑是Spring事务没有回滚,后来发现Spring事务正常回滚了,仔细研究了几个小时发现错出在了数据库上(还是基础不牢固),
                                    
                                    我用的数据库管理工具数SQLyong,在建表时有时候默认的引擎是MyIsAM模式。
                                    
                                    这种模式下不支持事务,得修改为InnoDB模式才可以,真是大意失荆州啊(也是学的不够扎实造成的),
                                    
                                    希望大家不要这样的犯错误,耽误了宝贵的学习时间。
                
   

猜你喜欢

转载自blog.csdn.net/qq_42891281/article/details/105133591