编程式事务管理:
自己手动控制事务,就叫做 编程式事务管理。
编程式事务管理可以清楚的定义事务的边界,可以实现细粒度的事务控制,比如可以通过代码控制事务何时开始,何时结束。
例如 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();
}
}
来源:https://blog.csdn.net/qq_29331365/article/details/101296099