一、事物的概念

  事务指逻辑上的一组操作,组成这组操作的各个单元,要不全部成功,要不全部不成功。

  作用:事物就是保证数据的一致性

  事物的特性:事务必须服从ISO/IEC所制定的ACID原则。ACID是原子性(atomicity)、一致性(consistency)、隔离性 (isolation)和持久性(durability)的缩写。

  原子性:原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响。

  一致性:一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。(如AB用户无论如何转账,总量不变,保持一致。)

  隔离性:隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。

  持久性:持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。

二、程序中事务控制

  一个业务的成功:调用的service是执行成功的,意味着service中调用的所有的dao是执行成功的。事务应该在Service层统一控制。

2.1 编程式事物

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

  Jdbc代码:  Conn.setAutoCommite(false);  // 设置手动控制事务

  Hibernate代码:  Session.beginTransaction();    // 开启一个事务

  细粒度的事务控制:可以对指定的方法、指定的方法的某几行添加事务控制。(比较灵活,但开发起来比较繁琐:每次都要开启、提交、回滚.)

2.2 声明式事物

  Spring提供了对事务的管理, 这个就叫声明式事务管理。

  Spring提供了对事务控制的实现。用户如果想用Spring的声明式事务管理,只需要在配置文件中配置即可;不想使用时直接移除配置。这个实现了对事务控制的最大程度的解耦。

  Spring声明式事务管理,核心实现就是基于Aop。

  粗粒度的事务控制:只能给整个方法应用事务,不可以对方法的某几行应用事务。(因为aop拦截的是方法。)

  Spring声明式事务管理器类:

    dbc技术:DataSourceTransactionManager

    Hibernate技术:HibernateTransactionManager

案例:

  dao层

@Repository
public class UserDao {
@Autowired
private JdbcTemplate jdbcTemplate;
publicvoid add(String name, Integer age) {
String sql = "INSERT INTO users(NAME, age) VALUES(?,?);";
intupdate = jdbcTemplate.update(sql, name, age);
System.out.println("updateResult:" + update);
}
}

  service层

@Autowired
private TransactionManager transactionManager; public void add() {
TransactionStatus status = null;
try {
status = transactionManager.begin();
String username = "zs" + System.currentTimeMillis();
String username2 = "ls" + System.currentTimeMillis();
String pwd = "123";
userDao.add(username, pwd);
// int i = 1/0;
userDao.add(username2, pwd);
transactionManager.commit(status);
} catch (Exception e) {
transactionManager.rollback(status);
e.printStackTrace();
}
}

  测试

public class UserTest {
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
UserService userService = (UserService) applicationContext.getBean("userService");
userService.add();
}
}

  手动事物管理类

@Component
public class TransactionUtils {
// 事物管理器
@Autowired
private DataSourceTransactionManager dataSourceTransactionManager;
public TransactionStatus begin() {
TransactionStatus transaction = dataSourceTransactionManager.getTransaction(new DefaultTransactionDefinition());
returntransaction;
}
public void commit(TransactionStatus transaction) {
dataSourceTransactionManager.commit(transaction);
}
public void rollback(TransactionStatus transaction) {
dataSourceTransactionManager.rollback(transaction);
}
}

  spring.xml(spring管理配置)

<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="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">
<!-- 开启注解 -->
<context:component-scanbase-package="com.stu"></context:component-scan>
<!-- 1. 数据源对象: C3P0连接池 -->
<beanid="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<propertyname="driverClass" value="com.mysql.jdbc.Driver"></property>
<propertyname="jdbcUrl" value="jdbc:mysql://localhost:3306/test"></property>
<propertyname="user" value="root"></property>
<propertyname="password" value=""></property>
</bean> <!-- 2. JdbcTemplate工具类实例 -->
<beanid="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<propertyname="dataSource" ref="dataSource"></property>
</bean> <!-- 配置事物 -->
<beanid="DataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<propertyname="dataSource" ref="dataSource"></property>
</bean>
</beans>

  注解版事物

<!--开启事物注解-->
<tx:annotation-driven transaction-manager="dataSourceTransactionManager"></tx:annotation-driven>

  service添加注解

@Transactional
public void add(){
String username = "zs"+System.currentTimeMillis();
String username2 = "ls"+System.currentTimeMillis();
String pwd = "123";
// try {
userDao.add(username,pwd);
// int i = 1/0; userDao.add(username2,pwd);
// }catch (Exception e){
// TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
// }
System.out.println("********************************方法执行完成。。。。。");
}

注意:

  1)事物是程序运行如果没有错误,会自动提交事物,如果程序运行发生异常,则会自动回滚。如果使用了try捕获异常时.一定要在catch里面手动回滚。

  事物手动回滚代码:TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

  2)数据库表中的主键如果是自增的,调用插入方法,即使被回滚了。该自增的ID也是已经被使用了

  3)spring报错org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.xxx] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

    原因:对应要注入的实现类没有 加注解,如component,dao层 @Repository 如service层 @Service

    解决:在相应的实现类加上注解即可

三、spring的传播行为

  Spring中事务的定义:Propagation(key属性确定代理应该给哪个方法增加事务行为。这样的属性最重要的部份是传播行为。)

  • PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。(默认)
  • PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。
  • PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。
  • PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。
  • PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
  • PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。
    @Transactional(
    readOnly = false, // 读写事务
    timeout = -1, // 事务的超时时间不限制
    noRollbackFor = ArithmeticException.class, // 遇到数学异常不回滚
    isolation = Isolation.DEFAULT, // 事务的隔离级别,数据库的默认
    propagation = Propagation.REQUIRED // 事务的传播行为
    )

    举例:

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void add(){
    String username = "zs"+System.currentTimeMillis();
    String pwd = "123";
    //无论该方法是否能完成走完,日志一定要存入
    logService.addLog();
    userDao.add(username,pwd);
    // int i = 1/0;
    System.out.println("********************************方法执行完成。。。。。");
    } class LogService {
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void addLog(){ }
    }

spring事物与传播行为的更多相关文章

  1. spring事物的传播行为

    1.spring事物的传播行为,主要是用来解决业务层拥有事物的方法,相互调用的问题. 2.声明事物, 在代码执行前,开启事务.代码执行完,提交事务 3.spring并没有提供事务具体的处理,而只是调用 ...

  2. spring事物的传播行为及隔离

    关于@Transactional注解: 添加事务注解1.使用 propagation 指定事务的传播行为, 即当前的事务方法被另外一个事务方法调用时如何使用事务, 默认取值为 REQUIRED, 即使 ...

  3. Spring事物的传播

    spring的事物对于同一个类内部调用是不会生效的. 比如一个ServiceA,里面有个方法x()和y().其中x没有配置事物,而y配置的有实物.如果是一个没有事物的ServiceB调用了Servic ...

  4. 【连接】Spring事物的传播行为

    http://blog.csdn.net/it_wangxiangpan/article/details/24180085 PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务, ...

  5. Spring 事物传播特性

    Spring 事物传播特性 这是Spring官方的定义 一共有7种 摘自源码省略了一部分 public interface TransactionDefinition { int PROPAGATIO ...

  6. Spring 事物隔离级别,事物传播行为

    Spring 框架中对于事物的管理,主要定义了一下四种属性: 事物的隔离(Isolation)级别 事物的传播行为(Propagation Behavior) 事物的超时时间(TImeout) 是否为 ...

  7. Spring事物传播行为

    Spring事物传播行为 Spring中事务的定义: Propagation(key属性确定代理应该给哪个方法增加事务行为.这样的属性最重要的部份是传播行为.)有以下选项可供使用: PROPAGATI ...

  8. spring事物传播机制与隔离级别

    转载自:http://www.blogjava.net/freeman1984/archive/2010/04/28/319595.html7个传播行为,4个隔离级别, Spring事务的传播行为和隔 ...

  9. 关于spring 事物传播性的研究

    spring的一大特色就是数据库事务管理方便,我们在代码中编写代码时,看不到事务的使用,关键是spring 使用了AOP进行事务拦截.   这篇文章主要介绍spring的事务传播性.   1.为什么要 ...

随机推荐

  1. Redis缓存你必须了解的!

    不管你是从事Python.Java.Go.PHP.Ruby等等… Redis都应该是一个比较熟悉的中间件.而大部分经常写业务代码的程序员,实际工作中或许只用到了set value.get value两 ...

  2. springboot~内嵌redis的使用

    对于单元测试来说,我们应该让它尽量保持单一环境,不要与网络资源相通讯,这样可以保证测试的稳定性与客观性,对于springboot这个框架来说,它集成了单元测试JUNIT,同时在设计项目时,你可以使用多 ...

  3. Python:strip 函数踩坑

    S.strip(chars=None) strip 函数用于去除字符串首尾的空格,当 chars 不为 None 时,则删除字符串首尾的 chars 中的字符. 当 chars=None 时,去除首尾 ...

  4. Mac下安装多版本python

    1.安装Homebrew 将命令行复制至终端,进行安装. /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/H ...

  5. 4.2WebHost配置「深入浅出ASP.NET Core系列」

    希望给你3-5分钟的碎片化学习,可能是坐地铁.等公交,积少成多,水滴石穿,谢谢关注. WebHost配置 覆盖配置文件和修改启动URL 覆盖配置文件和修改启动URL是经常使用的地方,覆盖配置文件可以自 ...

  6. rabbitmq高级消息队列

    rabbitmq使用 什么是消息队列 消息(Message)是指在应用间传送的数据.消息可以非常简单,比如只包含文本字符串,也可以很复杂,可以包含嵌入对象. 消息队列是一种应用间的通信方式,消息发送后 ...

  7. WCF优雅使用 KnownType标记的方法

    [KnownType("DerivedTypes")] [DataContract] public abstract class TaskBase { // other class ...

  8. C# 曲线上的点(一) 获取指定横坐标对应的纵坐标值

    获取直线上的点,很容易,那曲线呢?二阶贝塞尔.三阶贝塞尔.多段混合曲线,如何获取指定横坐标对应的纵坐标? 如下图形: 实现方案 曲线上的点集 Geometry提供了一个函数GetFlattenedPa ...

  9. Django 加载 app 中的urls

    在 blog app 下创建 urls.py, 定义该 app 下自有的 url : new/story from blog import views from django.conf import ...

  10. HTML/CSS快速入门

    Web概念 JavaWeb 使用java语言开发基于互联网的项目 软件架构 C/S架构:Client/Server 客户端/服务器 用户本地有一个客户端程序,在远程有一个服务端程序 如QQ,英雄联盟. ...