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

▼魔方 西西 提交于 2019-11-30 12:05:26

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


实体类 Dept.java:

public class Dept {
    private int deptId;
    private String deptName;

    public int getDeptId() {
        return deptId;
    }

    public void setDeptId(int deptId) {
        this.deptId = deptId;
    }

    public String getDeptName() {
        return deptName;
    }

    public void setDeptName(String deptName) {
        this.deptName = deptName;
    }

    @Override
    public String toString() {
        return "Dept{" +
                "deptId=" + deptId +
                ", deptName='" + deptName + '\'' +
                '}';
    }
}

DeptDao.java:

@Component // 加入 IOC 容器
public class DeptDao {

    @Resource // IOC 容器注入
    private JdbcTemplate jdbcTemplate;

    /**
     * 使用事务:
     *  定义到方法上:当前方法使用 spring 声明式事务;
     *  定义到类上:当前类中所有的方法 都使用 spring 声明式事务;
     *  定义到父类上:当执行父类中的方法的时候 使用事务;
     */
    @Transactional(
            // 是否是只读的;true 表示只读,即只能读取数据库数据,不能写入数据库;false 表示既可读也可写;
            readOnly = false,

            // 事务的超时时间;如果为 -1,表示不设置超时(此属性不一定会起作用,因为超时时间由数据库自己控制)
//            timeout = -1,

            /**
             * noRollbackFor:表示遇到指定的异常不回滚;ArithmeticException.class:表示数学异常;
             * noRollbackFor = ArithmeticException.class 即表示遇到 数学异常 不回滚;
             * (根据异常的类型)
             */
//            noRollbackFor = ArithmeticException.class,

            // rollbackFor:表示遇到指定的异常才回滚(其他异常不回滚)
//            rollbackFor = ArithmeticException.class,

            // 表示遇到名为 "ArithmeticException" 的异常不回滚(根据异常的名称)
//            noRollbackForClassName = "ArithmeticException"

//            isolation = Isolation.DEFAULT   // 事务的隔离级别(Isolation.DEFAULT 表示数据库的默认级别)

            /**
             * propagation:事务的传播行为
             *  Propagation.REQUIRED:表示当前方法必须在事务的环境下执行;
             *      如果当前运行的方法,已经存在事务,则当前事务会加入已经存在的事务,不会开启新的事务;
             *      (只存在一个事务,不会开启新的事务)
             *
             *  Propagation.REQUIRES_NEW:也表示当前方法必须在事务的环境下执行;
             *      如果当前运行的方法,已经存在事务,则当前事务会开启新的事务,然后挂起,等待已经存在的
             *      事务执行结束,然后再执行当前的事务;
             *      (始终会开启新的事务,可以存在多个事务)
             */
            propagation = Propagation.REQUIRED
    )
    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、事务管理器类 -->
    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>  <!-- 注入 dataSource 对象 -->
    </bean>

    <!-- 4、开启注解扫描:指定扫描哪个包下的注解 -->
    <context:component-scan base-package="com.spring.demo"/>

    <!-- 5、注解方式实现事务 -->
    <tx:annotation-driven transaction-manager="txManager"/>

</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();
    }
}

 

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