概述

  编程式事务控制

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

    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-事务控制的更多相关文章

  1. spring基于注解的事务控制

    pom配置: <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http ...

  2. spring基于xml的事务控制

    opm配置 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http: ...

  3. Spring 使用注解对事务控制详解与实例

    1.什么是事务 一荣俱荣,一损俱损,很多复杂的操作我们可以把它看成是一个整体,要么同时成功,要么同时失败. 事务的四个特征ACID: 原子性(Atomic):表示组成一个事务的多个数据库的操作的不可分 ...

  4. 笔面试复习(spring常用.jar包/事务/控制反转/bean对象管理和创建/springMVC工作原理/sql查询)

    ###spring常用jar包1.spring.jar是包含有完整发布模块的单个jar包.2.org.springframework.aop包含在应用中使用Spring的AOP特性时所需要的类.3.o ...

  5. spring boot 多数据源 + 事务控制

    1,首先在启动类加上@EnableTransactionManagement注解 package cn.bforce.common; import org.springframework.boot.S ...

  6. spring中编程式事务控制

    step1:配置xml文件 <!-- 事务管理bean --> <bean id="transactionManager" class="org.spr ...

  7. spring入门(三)【事务控制】

    在开发中需要操作数据库,进行增.删.改操作的过程中属于一次操作,如果在一个业务中需要更新多张表,那么任意一张表的更新失败,整个业务的更新就是失败,这时那些更新成功的表必须回滚,否则业务会出错,这时就要 ...

  8. Spring第八篇【XML、注解实现事务控制】

    前言 本博文主要讲解Spring的事务控制,如何使用Spring来对程序进行事务控制-. 一般地,我们事务控制都是在service层做的..为什么是在service层而不是在dao层呢??有没有这样的 ...

  9. Spring企业级程序设计 • 【第4章 Spring持久化层和事务管理】

    全部章节   >>>> 本章目录 4.1 配置数据源资源 4.1.1 JdbcTemplate介绍 4.1.2通过ComboPooledDataSource创建数据源 4.1. ...

随机推荐

  1. thinkphp model层外挪,以便多个站点可以通用

    /ThinkPHP/ThinkPHP.php  增加如下代码 //非原始代码defined('BASE_LOGIC') or define('BASE_LOGIC', THINK_PATH . '.. ...

  2. 02.iOS开发网络篇—HTTP协议

    iOS开发网络篇—HTTP协议 说明:apache tomcat服务器必须占用8080端口 一.URL 1.基本介绍 URL的全称是Uniform Resource Locator(统一资源定位符) ...

  3. 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.   ...

  4. Android——android学习(android目录与AndroidManifest解析)

    res目录:存放android项目的各种资源文件 layout:存放界面布局文件 values:存放各种xml格式的资源文件 strings.xml:字符串资源文件: colors.xml:颜色资源文 ...

  5. json、javaBean、xml互转的几种工具介绍 (转载)

    工作中经常要用到Json.JavaBean.Xml之间的相互转换,用到了很多种方式,这里做下总结,以供参考. 现在主流的转换工具有json-lib.jackson.fastjson等,我为大家一一做简 ...

  6. SG函数题目

    HDU Fibonacci again and again 思路: 把整个游戏看成三个子游戏,然后求游戏的和 关键理解g(x) = mex(g(y), y€f(x)) , f(x)表示由x点可达的点, ...

  7. 输出sed的重定向

    默认情况下,sed编辑器会将进步的结果输出到STDOUT上,你可以在shll脚本中使用所有重订向sed编辑器输出的标准方法. 你可以在脚本中用反引号来将sed编辑器命令的输出重定向到一个变量中供后面使 ...

  8. SpringMVC后缀

    <!-- 在这里,使用*.html为后缀的URL都能被baobaotao Servlet截获,进而转由SpringMVC框架进行处理.在 Struts框架中,一般将URL后缀配置为*.do:在w ...

  9. Data truncation: Truncated incorrect DOUBLE value 解决方案

    1.情况限制 此处的错误解决方案只讨论: 在使用Mybatis时,传入数组且使用<foreach>标签时出现此种报错: 2.报错案例 mapper.java /** * @Descript ...

  10. sscanf的用法(转)

    队长做上海邀请赛的I题时遇到一个棘手的问题,字符串的处理很麻烦,按传统的gets全部读入的话还要做N多处理,太浪费时间. 回来之后搜了一下sscanf的用法发现可以很好的解决这一类问题,各种百度,转来 ...