spring来了-06-事务控制
概述
编程式事务控制
自己手动控制事务,就叫做编程式事务控制。
Jdbc代码:
Conn.setAutoCommite(false); // 设置手动控制事务
Hibernate代码:
Session.beginTransaction(); // 开启一个事务
【细粒度的事务控制: 可以对指定的方法、指定的方法的某几行添加事务控制】
(比较灵活,但开发起来比较繁琐: 每次都要开启、提交、回滚.)
spring提供的事务控制
声明式事务控制
Spring提供了对事务的管理, 这个就叫声明式事务管理。
Spring提供了对事务控制的实现。用户如果想用Spring的声明式事务管理,只需要在配置文件中配置即可; 不想使用时直接移除配置。这个实现了对事务 控制的最大程度的解耦。
Spring声明式事务管理,核心实现就是基于Aop。
【粗粒度的事务控制: 只能给整个方法应用事务,不可以对方法的某几行应用事务。】
(因为aop拦截的是方法。)
Spring声明式事务管理器类:
Jdbc技术:DataSourceTransactionManager
Hibernate技术:HibernateTransactionManager
package cn.fuyi.a_tx;
public class Dept {
private Integer deptId;
private String dname;
public Integer getDeptId() {
return deptId;
}
public void setDeptId(Integer deptId) {
this.deptId = deptId;
}
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
}
package cn.fuyi.a_tx;
import org.springframework.jdbc.core.JdbcTemplate;
public class DeptDao {
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public void save(Dept dept) {
String sql = "insert into dept(dname) values(?)";
jdbcTemplate.update(sql, dept.getDname());
}
}
package cn.fuyi.a_tx;
public class DeptService {
private DeptDao deptDao;
public void setDeptDao(DeptDao deptDao) {
this.deptDao = deptDao;
}
public void save(Dept dept) {
deptDao.save(dept);
int i = 1/0;
deptDao.save(dept);
}
}
<?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: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">
<!-- dataSource配置 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql:///mydb"></property>
<property name="user" value="root"></property>
<property name="password" value="950613"></property>
<property name="initialPoolSize" value="4"></property>
<property name="maxPoolSize" value="9"></property>
<property name="maxStatements" value="100"></property>
<property name="acquireIncrement" value="2"></property>
</bean>
<!-- JdbcTemplate工具类实例 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- dao实例 -->
<bean id="deptDao" class="cn.fuyi.a_tx.DeptDao">
<property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean>
<!-- service实例 -->
<bean id="deptService" class="cn.fuyi.a_tx.DeptService">
<property name="deptDao" ref="deptDao"></property>
</bean>
<!-- spring的声明式事务配置 -->
<!-- 1.配置事务管理器类 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 2.配置事务增强(如何管理事务?) -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*save*" read-only="false" isolation="DEFAULT" propagation="REQUIRED"/>
<tx:method name="*find*" read-only="true" isolation="DEFAULT" propagation="REQUIRED"/>
<tx:method name="*get*" read-only="true" isolation="DEFAULT" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!-- 3.AOP配置:拦截哪些方法(切入点表达式 + 应用上面的事务增强配置) -->
<aop:config>
<aop:pointcut expression="execution(* cn.fuyi.a_tx.DeptService.*(..))" id="pt"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt"/>
</aop:config>
</beans>
package cn.fuyi.a_tx;
import static org.junit.Assert.*;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
private ApplicationContext ac = new ClassPathXmlApplicationContext("cn/fuyi/a_tx/beans.xml");
@Test
public void testTx1() throws Exception {
DeptService ds = (DeptService) ac.getBean("deptService");
Dept dept = new Dept();
dept.setDname("哈2哈");
ds.save(dept);
}
}
/**Output
数据库回滚
*/
注解方式实现
使用注解实现Spring的声明式事务管理,更加简单!
步骤:
1) 必须引入Aop相关的jar文件
2) bean.xml中指定注解方式实现声明式事务管理以及应用的事务管理器类
3)在需要添加事务控制的地方,写上: @Transactional
@Transactional注解:
1)应用事务的注解
2)定义到方法上: 当前方法应用spring的声明式事务
3)定义到类上: 当前类的所有的方法都应用Spring声明式事务管理;
4)定义到父类上: 当执行父类的方法时候应用事务。
<?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: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"> <!-- 1. 数据源对象: C3P0连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql:///hib_demo"></property>
<property name="user" value="root"></property>
<property name="password" value="root"></property>
<property name="initialPoolSize" value="3"></property>
<property name="maxPoolSize" value="10"></property>
<property name="maxStatements" value="100"></property>
<property name="acquireIncrement" value="2"></property>
</bean> <!-- 2. JdbcTemplate工具类实例 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean> <!-- 事务管理器类 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean> <!-- 开启注解扫描 -->
<context:component-scan base-package="cn.itcast.b_anno"></context:component-scan> <!-- 注解方式实现事务: 指定注解方式实现事务 -->
<tx:annotation-driven transaction-manager="txManager"/>
</beans>
事务属性
@Transactional(
readOnly = false, // 读写事务
timeout = -1, // 事务的超时时间不限制
noRollbackFor = ArithmeticException.class, // 遇到数学异常不回滚
isolation = Isolation.DEFAULT, // 事务的隔离级别,数据库的默认
propagation = Propagation.REQUIRED // 事务的传播行为
)
public void save(Dept dept){
deptDao.save(dept);
int i = 1/0;
deptDao.save(dept);
}
事务传播行为:
Propagation.REQUIRED
指定当前的方法必须在事务的环境下执行;
如果当前运行的方法,已经存在事务, 就会加入当前的事务;
Propagation.REQUIRED_NEW
指定当前的方法必须在事务的环境下执行;
如果当前运行的方法,已经存在事务: 事务会挂起; 会始终开启一个新的事务,执行完后; 刚才挂起的事务才继续运行。
举例:
1.Propagation.REQUIRED
Class Log{
@Propagation.REQUIRED
insertLog();
} Class DeptDao{
@Propagation.REQUIRED
Void saveDept(){
insertLog(); // 加入当前事务
.. 出现异常, 会回滚
saveDept();
}
} 2.Propagation.REQUIRED_NEW
Class Log{
@Propagation.REQUIRED_NEW
insertLog();
} Class DeptDao{
@Propagation.REQUIRED
Void saveDept(){
insertLog(); // 始终开启事务
.. 异常, 日志不会回滚
saveDept();
}
}
测试:
package cn.fuyi.a_tx; import javax.annotation.Resource; import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional; @Repository
public class LogDao { @Resource
private JdbcTemplate jdbcTemplate; @Transactional(propagation=Propagation.REQUIRES_NEW)
public void insertLog() {
String sql = "insert into log_ values('在保存dept。。。')";
jdbcTemplate.update(sql);
}
} package cn.fuyi.a_tx; import javax.annotation.Resource; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional; @Service("deptService")
public class DeptService { @Resource(name="deptDao")
private DeptDao deptDao; @Resource(name="logDao")
private LogDao logDao; @Transactional(
propagation=Propagation.REQUIRED
)
public void save(Dept dept) {
logDao.insertLog();
int i = 1/0;
deptDao.save(dept);
}
}
spring来了-06-事务控制的更多相关文章
- spring基于注解的事务控制
pom配置: <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http ...
- spring基于xml的事务控制
opm配置 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http: ...
- Spring 使用注解对事务控制详解与实例
1.什么是事务 一荣俱荣,一损俱损,很多复杂的操作我们可以把它看成是一个整体,要么同时成功,要么同时失败. 事务的四个特征ACID: 原子性(Atomic):表示组成一个事务的多个数据库的操作的不可分 ...
- 笔面试复习(spring常用.jar包/事务/控制反转/bean对象管理和创建/springMVC工作原理/sql查询)
###spring常用jar包1.spring.jar是包含有完整发布模块的单个jar包.2.org.springframework.aop包含在应用中使用Spring的AOP特性时所需要的类.3.o ...
- spring boot 多数据源 + 事务控制
1,首先在启动类加上@EnableTransactionManagement注解 package cn.bforce.common; import org.springframework.boot.S ...
- spring中编程式事务控制
step1:配置xml文件 <!-- 事务管理bean --> <bean id="transactionManager" class="org.spr ...
- spring入门(三)【事务控制】
在开发中需要操作数据库,进行增.删.改操作的过程中属于一次操作,如果在一个业务中需要更新多张表,那么任意一张表的更新失败,整个业务的更新就是失败,这时那些更新成功的表必须回滚,否则业务会出错,这时就要 ...
- Spring第八篇【XML、注解实现事务控制】
前言 本博文主要讲解Spring的事务控制,如何使用Spring来对程序进行事务控制-. 一般地,我们事务控制都是在service层做的..为什么是在service层而不是在dao层呢??有没有这样的 ...
- Spring企业级程序设计 • 【第4章 Spring持久化层和事务管理】
全部章节 >>>> 本章目录 4.1 配置数据源资源 4.1.1 JdbcTemplate介绍 4.1.2通过ComboPooledDataSource创建数据源 4.1. ...
随机推荐
- 改变CSS样式
改变CSS样式 1.改变HTML元素样式的语法 //改变HTML样式的语法 document.getElementById(id).style.property = new style 例子: < ...
- SqlSever基础 Upper函数 返回字符串的大写形式
镇场诗:---大梦谁觉,水月中建博客.百千磨难,才知世事无常.---今持佛语,技术无量愿学.愿尽所学,铸一良心博客.------------------------------------------ ...
- application/x-www-form-urlencoded
在Form元素的语法中,EncType表明提交数据的格式 用 Enctype 属性指定将数据回发到服务器时浏览器使用的编码类型. 下边是说明: application/x-www-form-urlen ...
- 表头表侧边固定,方法二,丫的,复制td
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...
- CodeForces 219B Special Offer! Super Price 999 Bourles!
Special Offer! Super Price 999 Bourles! Time Limit:1000MS Memory Limit:262144KB 64bit IO For ...
- C# POST与Get数据
引用DLL 普通Get数据和Post数据 public static string Get(string URL) { String ReCode = string.Empty; try { Http ...
- CANopen笔记1
CAN现场总线只定义了OSI网络模型的第一层(物理层) 和第二层(数据链路层) ,而这两层一般已被CAN硬件完全实现了.由于没有规定应用层,本身并不完整,需要一个高层协议来定义CAN报文中的11/29 ...
- .net 浏览器请求过程(图)
大致: 细节: (信息来源于传智播客教学视频)
- iOS - OC NSRect 位置和尺寸
前言 结构体 这个结构体用来表示事物的坐标点和宽高度. typedef CGRect NSRect; struct CGRect { CGPoint origin; CGSize size; }; t ...
- aop前传之代理
一.jdk提供proxy类对目标对象实现代理,简单的说对方法的调用交给代理对象来操作. 代理目标 代理的具体实现: 代理测试; 简单说:利用proxy生成一个委托类实现代理.这个委托类是目标类的接口的 ...