概述

  编程式事务控制

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

    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. 关于跨域的ajax

    $.getJSON("http://query.yahooapis.com/v1/public/yql?callback=?", { q: "select * from ...

  2. The Pilots Brothers' refrigerator

    2965 he Pilots Brothers' refrigerator Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 1 ...

  3. c++ stl string char* 向 string 转换的问题

    请看下面代码 string AddString(const string& a,const string & b) { return a + b; } int _tmain(int a ...

  4. Ajax发送POST请求的心路历程

    好多年前就在项目中用ajax实现了页面部分数据的发送,当时用的是GET方法. 这次用POST方法实现同样的功能,竟然花费了不少的时间! ① 关于JQuery ajax的配置项说明 url : 请求的u ...

  5. Hibernate——基础及XML配置

    1.入门 hibernate是跟数据库打交道的,一般跟数据库打交道的都不简单 原始.底层直接的一些操作.编码量比较大.费时.用框架高效 把原来一点一点实现的东西,现在给个半成品,不用在这上边发时间,把 ...

  6. ettercap

    作者: 官网:http://ettercap.github.io/ettercap/ 源码:https://github.com/Ettercap/ettercap 功能:arp欺骗

  7. Python数据类型之列表

    一.基本数据类型 整数:int 字符串:str(注:\t等于一个tab键) 布尔值: bool 列表:list (元素的集合) 列表用[] 元祖:tuple 元祖用() 字典:dict注:所有的数据类 ...

  8. ubuntu下配置hosts

    由于Chrome浏览器访问问题,需要配置hosts. 在Ubuntu系统下,需要修改/etc/hosts文件,修改完之后要重启网络.具体过程如下:1.修改hostssudo vi /etc/hosts ...

  9. iOS - OC SingleClass 单例类

    前言 单例对象能够被整个程序所操作.对于一个单例类,无论初始化单例对象多少次,也只能有一个单例对象存在,并且该对象是全局的,能够被整个系统访问到. 特点: 在内存中只有一个实例 提供一个全局的访问点 ...

  10. c++ vector 简单实现。

    第二次修改: 1)熟悉基本的模板编程,头文件和定义必须放到一起. 2)熟悉内存管理模板类 allocator<T>. 1.使用标准库的内存管理类 allocator<T> 代替 ...