spring学习笔记(十二):使用 xml 方式实现 spring 的声明式事务管理(使用对 jdbc 的支持)

允我心安 提交于 2019-11-30 10:46:57

编程式事务管理:

自己手动控制事务,就叫做 编程式事务管理。

编程式事务管理可以清楚的定义事务的边界,可以实现细粒度的事务控制,比如可以通过代码控制事务何时开始,何时结束。

例如 jdbc、hibernate 就是编程式事务管理,spring 中不提倡使用。

jdbc 代码:

        conn.setAutoCommite(false);  // 设置 手动控制事务

hibernate 代码:   

        session.beginTransaction();    // 开启一个事务

细粒度 的事务控制:可以对指定的方法、或指定方法的某几行添加事务控制;

比较灵活,但开发起来比较繁琐,每次都要开启、提交、回滚。

声明式事务管理:

如果不需要细粒度的事务控制,可以使用声明式事务。

spring 中提供的对事务的管理,就叫做声明式事务管理。

只需要在 spring 配置文件中做一些配置,即可将操作纳入到事务管理中,解除了和代码的耦合。

spring 声明式事务管理,核心实现就是基于 AOP。

Spring声明式事务管理器类:

        Jdbc技术:DataSourceTransactionManager

        Hibernate技术:HibernateTransactionManager


使用 xml 方式实现 spring 的声明式事务管理 需要引入 aop 名称空间 和 tx 名称空间。


DeptDao.java:

public class DeptDao {
    // JdbcTemplate 模板:通过 IOC 注入(使用对 jdbc 的支持)
    private JdbcTemplate jdbcTemplate;
    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    // 保存数据
    public void save() {
        String sql = "insert into t_dept(deptName) values('财务部')";

        // 第一次保存数据
        jdbcTemplate.update(sql);

        // 模拟异常:事务回滚(第一次保存数据 应该也是失败的)
        int i = 1 / 0;

        // 第二次保存数据
        jdbcTemplate.update(sql);
    }
}

bean.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!--suppress ALL -->
<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: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
        https://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx
        https://www.springframework.org/schema/tx/spring-tx.xsd">

    <!-- 1、配置数据源对象:使用 C3P0 连接池 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <!-- 数据库配置 -->
        <property name="driverClass" value="com.mysql.jdbc.Driver"/>
        <property name="jdbcUrl" value="jdbc:mysql:///hib_demo"/>
        <property name="user" value="root"/>
        <property name="password" value="root"/>

        <!-- 连接池配置 -->
        <property name="initialPoolSize" value="3"/>    <!-- 初始化连接池数量 -->
        <property name="maxPoolSize" value="10"/>       <!-- 最大连接池数量 -->
        <property name="maxStatements" value="100"/>    <!-- 最大执行 sql 语句个数 -->
        <property name="acquireIncrement" value="2"/>   <!-- 连接池不够用时,每次增加的个数 -->
    </bean>

    <!-- 2、创建 jdbcTemplate 对象 -->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <!-- 注入数据源对象:下面两种方法不能同时存在 -->
        <!--<constructor-arg ref="dataSource"/>-->      <!-- 通过构造方法注入对象 -->
        <property name="dataSource" ref="dataSource"/>  <!-- 通过 setter 方法注入对象 -->
    </bean>

    <!-- 3、创建 DeptDao 对象 -->
    <bean id="deptDao" class="com.spring.demo.DeptDao">
        <property name="jdbcTemplate" ref="jdbcTemplate"/> <!-- 注入 jdbcTemplate 模板对象 -->
    </bean>

    <!-- 4、spring 声明式事务管理配置 -->
    <!-- 4.1、配置事务管理器类:控制事务的具体实现 -->
    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>  <!-- 注入 dataSource 对象 -->
    </bean>

    <!-- 4.2、配置事务增强:即如何管理事务;transaction-manager="txManager":指定事务管理器类,即通过哪个类控制事务的具体实现 -->
    <tx:advice id="txAdvice" transaction-manager="txManager">
        <tx:attributes>
            <!-- 给相应的方法设置事务属性:即如何管理事务 -->
            <tx:method name="*save*" read-only="false"/>    <!-- 包含 save 的方法 -->
            <tx:method name="find*" read-only="true"/>      <!-- 以 find 开头的方法 -->
        </tx:attributes>
    </tx:advice>

    <!-- 4.3、AOP配置:拦截哪些方法(切入点表达式) + 引用上面的事务增强配置 -->
    <aop:config>
        <!-- 指定拦截哪些方法:即哪些方法需要使用事务 -->
        <aop:pointcut expression="execution(* com.spring.demo.DeptDao.save(..)))" id="pointCut"/>
        <!-- 指定事务增强配置:即拦截的方法应该怎样去管理事务 -->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pointCut"/>
    </aop:config>
</beans>

测试程序 Demo.java:

public class Demo {
    @Test
    public void testJdbc(){
        // 加载配置文件
        ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");

        // 从 IOC 容器中获取对象
        DeptDao deptDao = (DeptDao) context.getBean("deptDao");
        deptDao.save();
    }
}

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!