一、事物的概念

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

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

  事物的特性:事务必须服从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. 『集群』002 Slithice 集群配置工具 的使用

    Slithice 集群配置工具 的使用 Slithice集群配置工具 主界面 在测试 Slithice 的 Demo 中,我配置了 7个服务端: 一个 WCF 的 中央服务端: 两个 WCF 的 成员 ...

  2. Linux磁盘管理及LVM讲解(week2_day2)--技术流ken

    硬盘接口 从整体的角度上,硬盘接口分为IDE.SATA.SCSI和SAS四种,IDE接口硬盘多用于家用产品中,也部分应用于服务器,SCSI接口的硬盘则主要应用于服务器市场,而SAS只在高端服务器上,价 ...

  3. 改行了,学C#

    C#数组: 定义方法 ]; ,]; //这个是二维数组 只有这一种定义方法,不像java有多种定义方法.等号前面在栈中初始化类型为一维数组类型(int[])或二维数组类型(int[,])的存储堆中地址 ...

  4. WebSocketSharp 的使用

    Server 端示例代码: class Program { static void Main(string[] args) { var wssv = new WebSocketServer(" ...

  5. Docker 容器镜像删除

    1.停止所有的container,这样才能够删除其中的images: docker stop $(docker ps -a -q) 如果想要删除所有container的话再加一个指令: docker ...

  6. c#中缓存的使用

    缓存的使用: 缓存是分布式系统中的重要组件,主要解决高并发,大数据场景下,热点数据访问的性能问题.提供高性能的数据快速访问,提高数据的读取速度.因为服务器和应用客户端之间存在着流量的瓶颈,所以读取大容 ...

  7. Arrays工具、二维数组以及LeetCode练习题

    1 Arrays PS:Arrays位于java.util包下 int binarySearch(type[] a, type key); 使用二分法查询 key 元素在 a 数组中的索引,如果数组不 ...

  8. Android项目实战登录&注册

    由于项目中大部分界面都有一个后退键和一个标题栏,为避免代码冗杂以及便于利用,我们可以将后推荐和标题栏单独抽取出来定义一个标题栏布局,在 res/layout 目录下新建一个 Layout resour ...

  9. 通用HttpClientUtil工具类

    package com.*.utils; import java.io.IOException; import java.net.URI; import java.util.ArrayList; im ...

  10. Centos7 二进制安装 Kubernetes 1.13

    目录 1.目录 1.1.什么是 Kubernetes? 1.2.Kubernetes 有哪些优势? 2.环境准备 2.1.网络配置 2.2.更改 HOSTNAME 2.3.配置ssh免密码登录登录 2 ...