Spring(三)事务处理、整合Mybatis

作者: 一直想上树的猪 | 来源:发表于2018-12-10 00:09 被阅读18次

    一、事务处理

    1.事务传播行为

    一共七种:

    • PROPAGATION_REQUIRED 如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是 最常见的选择。
    • PROPAGATION_SUPPORTS 支持当前事务,如果当前没有事务,就以非事务方式执行。
    • PROPAGATION_MANDATORY 使用当前的事务,如果当前没有事务,就抛出异常。
    • PROPAGATION_REQUIRES_NEW 新建事务,如果当前存在事务,把当前事务挂起。
    • PROPAGATION_NOT_SUPPORTED 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
    • PROPAGATION_NEVER 以非事务方式执行,如果当前存在事务,则抛出异常。
    • PROPAGATION_NESTED 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED 类似的操作。

    2.事务隔离级别

    Isolation 属性一共支持五种事务设置,具体介绍如下:

    • DEFAULT 使用数据库设置的隔离级别 ( 默认 ) ,由 DBA 默认的设置来决定隔离级别 .
    • READ_UNCOMMITTED 未提交读 会出现脏读、不可重复读、幻读 ( 隔离级别最低,并发性能高 )
    • READ_COMMITTED 已提交读 会出现不可重复读、幻读问题(锁定正在读取的行)
    • REPEATABLE_READ 可重复读 会出幻读(锁定所读取的所有行)
    • SERIALIZABLE 可序列化 保证所有的情况不会发生(锁表)

    3.几种事务出现问题的区别

    不可重复读的重点是修改
    同样的条件 , 你读取过的数据 , 再次读取出来发现值不一样了
    幻读的重点在于新增或者删除
    同样的条件 , 第 1 次和第 2 次读出来的记录数不一样

    4.Spring在TransactionDefinition接口中定义这些属性

    在TransactionDefinition接口中定义了五个不同的事务隔离级别

    • ISOLATION_DEFAULT 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别.另外四个与JDBC的隔离级别相对应
    • ISOLATION_READ_UNCOMMITTED 这是事务最低的隔离级别,它允许别外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读
    • ISOLATION_READ_COMMITTED 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现,但是可能会出现不可重复读和幻像读。
    • ISOLATION_REPEATABLE_READ 这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。
    • ISOLATION_SERIALIZABLE 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻像读。

    5.Spring中的声明式事务控制

    Spring中控制事务的方式采用声明式的事务控制。为我们提供了不同的事务控制器的切面(注意:spring的事物控制器就是一个aop,如果面试时问你是否用spring的aop 。一定要回答用过,起码事务上用到了。)

    6.配置Spring的基于dataSourse的事务控制器,适用于jdbc、mybatis,DataSourceAransactionManager:基于数据源的事务控制的切面

    7.代码实现

    1.导入jar包:

    spring-jdbc.jar
    spring-tx.jar
    spring-aop.jar
    2.在spring的配置文件中配置事务

    <?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:tx="http://www.springframework.org/schema/tx" 
        xmlns:context="http://www.springframework.org/schema/context"
        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">
         <!-- 需要在配置文件的头中开启tx的命名空间 -->
         <!-- 先配置基于dataSource的事务管理器的切面(AOP)-->
         <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <!-- 该切面需要一个datasource -->
            <property name="dataSource">
                <ref bean="dataSource"/>
            </property>
         </bean>
        <!-- 配置事物传播行为以及事物隔离级别 -->
        <tx:advice id="txAdvice" transaction-manager="transactionManager">
            <tx:attributes>
                <!-- 
                name:需要参与到事物控制中的方法名。可以使用*来通配
                propagation:事物的传播行为。REQUIRED 必须要运行在一个事务中
                isolation:事物的隔离级别 。DEFAULT以数据默认的隔离级别为主。
                read-only:只读事物。只读并不会做事物提交与回滚。他会优化查询执行的效率。所以如果不是DML操作。建议都需要拥有只读事物
                 -->
                <tx:method name="add*" propagation="REQUIRED" isolation="DEFAULT"/>
                <tx:method name="drop*" propagation="REQUIRED"/>
                <tx:method name="modify*" propagation="REQUIRED"/>
                <tx:method name="*" read-only="true"/>
            </tx:attributes>
        </tx:advice>
        <!-- 配置切点 -->
        <aop:config>
            <aop:pointcut expression="execution(* com.tinner.service.impl.*.*(..))" id="mypointcut"/>
            <aop:advisor advice-ref="txAdvice" pointcut-ref="mypointcut"/>
        </aop:config>
    </beans>
    

    二、整合mybatis

    1.在实现Spring与Mybatis的整合时,需要导入两个框架的jar包。注意:spring与mybatis整合时,需要额外导入一个非常重要的jar包 spring-mybatis.jar

    2.Spring中提供三种方式

    2.1 sqlSessionTemplate

    Autowire属性:自动装配
    1。byName通过名称完成自动注入。要求注入与被注入的属性的名称相同
    2。byType 通过类型完成自动注入。要求名称可以不相同,但是类型必须是同类型,或者是父类,或者已实现的接口类型。
    default-autowire :<beans>标签中的该属性表示全局性的自动装配的设置

    <?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:p="http://www.springframework.org/schema/p"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
            <!-- 通过命名空间配置解析配置文件的工具类 -->
           <context:property-placeholder location="/db.properties"/>
         <!-- 配置数据源。dbcp  c3p0 druid。。。 -->
    <!-- 配置数据源 dataSource -->
        <!-- <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
            <property name="url" value="${jdbc.url}" />
            <property name="username" value="${jdbc.username}" />
            <property name="password" value="${jdbc.password}" />
            <property name="driverClassName" value="${jdbc.driver}" />
            <property name="maxActive" value="10" />
            <property name="minIdle" value="5" />
        </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/test001"></property>
            <property name="username" value="root"></property>
            <property name="password" value="root"></property>
        </bean>
        
        <!-- 配置创建mybatis上下文对象的工具类 -->
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean" >
            <!-- 配置datasource -->
            <property name="dataSource" ref="dataSource"/>
            <!-- 导入其他配置文件 -->
            <property name="mapperLocations" value="com/tinner/pojo/*.xml"/>
        </bean>
        
        <!-- 配置sqlsessiontemplate -->
        <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
            <!-- 通过构造方法完成sqlsessionfactory的注入 -->
            <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"/>
        </bean>
        
        <!-- 配置userdao -->
        <bean id="userDao" class="com.tinner.dao.impl.UserDaoImpl" autowire="byName"/>
    </beans>
    
    2.2 SqlSessionDaoSupport方式

    配置文件:

    <!-- 配置创建mybatis上下文对象的工具类 -->
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean" >
            <!-- 配置datasource -->
            <property name="dataSource" ref="dataSource"/>
            <!-- 导入其他配置文件 -->
            <property name="mapperLocations" value="com/tinner/pojo/*.xml"/>
        </bean>
        <!-- 配置userdao -->
        <bean id="userDao" class="com.tinner.dao.impl.UserDaoImpl" >
        <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
        </bean>
    

    代码:

    public class UserDaoImpl extends SqlSessionDaoSupport implements UserDao {
        //将SqlSessionFactory交给SqlSessionDaoSupport
        public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
            super.setSqlSessionFactory(sqlSessionFactory);
        }
        @Override
        public void insertUser(Users user) {
            this.getSqlSession().insert("com.tinner.pojo.Users.insertUser", user);
        }
    }
    
    2.3 使用代理类生成接口实现类的方式
    <?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:p="http://www.springframework.org/schema/p"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
            <!-- 通过命名空间配置解析配置文件的工具类 -->
           <context:property-placeholder location="/db.properties"/>
         <!-- 配置数据源。dbcp  c3p0 druid。。。 -->
    <!-- 配置数据源 dataSource -->
        <!-- <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
            <property name="url" value="${jdbc.url}" />
            <property name="username" value="${jdbc.username}" />
            <property name="password" value="${jdbc.password}" />
            <property name="driverClassName" value="${jdbc.driver}" />
            <property name="maxActive" value="10" />
            <property name="minIdle" value="5" />
        </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/test001"></property>
            <property name="username" value="root"></property>
            <property name="password" value="root"></property>
        </bean>
        <!-- 配置创建mybatis上下文对象的工具类 -->
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean" >
            <!-- 配置datasource -->
            <property name="dataSource" ref="dataSource"/>
        </bean>
        <!-- 配置扫描接口与映射配置文件对象  该对象会去创建接口的代理对象。并且根据接口的名称作为该对象的默认名称-->
        <bean  class="org.mybatis.spring.mapper.MapperScannerConfigurer">
            <property name="basePackage" value="com.tinner.mapper"/>
            <property name="sqlSessionFactory" ref="sqlSessionFactory"/>    
        </bean>
    </beans>
    

    相关文章

      网友评论

        本文标题:Spring(三)事务处理、整合Mybatis

        本文链接:https://www.haomeiwen.com/subject/yhylhqtx.html