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. ...
随机推荐
- thinkphp model层外挪,以便多个站点可以通用
/ThinkPHP/ThinkPHP.php 增加如下代码 //非原始代码defined('BASE_LOGIC') or define('BASE_LOGIC', THINK_PATH . '.. ...
- 02.iOS开发网络篇—HTTP协议
iOS开发网络篇—HTTP协议 说明:apache tomcat服务器必须占用8080端口 一.URL 1.基本介绍 URL的全称是Uniform Resource Locator(统一资源定位符) ...
- Using Post-Form Trigger In Oracle Forms
Post-Form trigger in Oracle Forms fires during the Leave the Form process, when a form is exited. ...
- Android——android学习(android目录与AndroidManifest解析)
res目录:存放android项目的各种资源文件 layout:存放界面布局文件 values:存放各种xml格式的资源文件 strings.xml:字符串资源文件: colors.xml:颜色资源文 ...
- json、javaBean、xml互转的几种工具介绍 (转载)
工作中经常要用到Json.JavaBean.Xml之间的相互转换,用到了很多种方式,这里做下总结,以供参考. 现在主流的转换工具有json-lib.jackson.fastjson等,我为大家一一做简 ...
- SG函数题目
HDU Fibonacci again and again 思路: 把整个游戏看成三个子游戏,然后求游戏的和 关键理解g(x) = mex(g(y), y€f(x)) , f(x)表示由x点可达的点, ...
- 输出sed的重定向
默认情况下,sed编辑器会将进步的结果输出到STDOUT上,你可以在shll脚本中使用所有重订向sed编辑器输出的标准方法. 你可以在脚本中用反引号来将sed编辑器命令的输出重定向到一个变量中供后面使 ...
- SpringMVC后缀
<!-- 在这里,使用*.html为后缀的URL都能被baobaotao Servlet截获,进而转由SpringMVC框架进行处理.在 Struts框架中,一般将URL后缀配置为*.do:在w ...
- Data truncation: Truncated incorrect DOUBLE value 解决方案
1.情况限制 此处的错误解决方案只讨论: 在使用Mybatis时,传入数组且使用<foreach>标签时出现此种报错: 2.报错案例 mapper.java /** * @Descript ...
- sscanf的用法(转)
队长做上海邀请赛的I题时遇到一个棘手的问题,字符串的处理很麻烦,按传统的gets全部读入的话还要做N多处理,太浪费时间. 回来之后搜了一下sscanf的用法发现可以很好的解决这一类问题,各种百度,转来 ...