一、事物的概念

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

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

  事物的特性:事务必须服从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. java~集合分组groupby的实现

    对于数据聚合来说,分组操作是很常见的,在.net里有lambda和linq,而在java里也有lambda,现在我们来实现对一个集合进行分组. 一 准备工作,有两个类型 @Value class It ...

  3. docker 安装 MySQL 8,并减少内存占用 记录

    目前vps 1cpu 512m内存 MySQL内存占用77% ,约350m ,经过修改配置文件优化后如下 $ ps aux 进入docker bash $ docker exec -it pwc-my ...

  4. linux 指令备忘

    linux 指令备忘 1.ls [选项] [目录名 | 列出相关目录下的所有目录和文件 -a 列出包括.a开头的隐藏文件的所有文件 -A 通-a,但不列出"."和"..& ...

  5. vs2015安装编辑神器:resharper10.0

    在平时的开发工作中,作为一名程序员,难免会想办法找到适合自己的开发编辑器.这款插件来自JetBrains公司.接下来就来教大家如何对这款软件进行安装与破解. 1:首先下载与安装.如果没有找到适合的资源 ...

  6. GraphQL基础篇

    最近参与了一个大型项目,大型项目随着系统业务量的增大,不同的应用和系统共同使用着许多的服务接口API,而随着业务的变化和发展,不同的应用对相同资源的不同使用方法最终会导致需要维护的服务API数量呈现爆 ...

  7. HotSpot 虚拟机垃圾回收算法实现

    作为使用范围最广的虚拟机之一HotSpot,必须对垃圾回收算法的执行效率有严格的考量,只有这样才能保证虚拟机高效运行 枚举根节点 从可达性分析中从 GC Roots 节点找引用链这个操作为例,可以作为 ...

  8. 使用 DotNet CLI 创建自定义的 WPF 项目模板

    描述 当我们安装完 DotNetCore 3.0 版本的 SDK 后,我们就可以创建基于 DotNetCore 的 WPF 项目模板,通过如下 CLI 可以方便快捷的创建并运行我们的项目: dotne ...

  9. video.js 一个页面同时播放多个视频

    $(data).each(function(i, item) { // innerHTML += '<li type-id="'+item.id+'">'+ // '& ...

  10. 百度地图API开发一——仿照现有测距效果实现测面功能

      最近做了一个百度地图API的开发项目,里面有测量距离和测量面积的功能需求.测量距离百度给出了封装好的javascript包——BMapLib.DistanceTool,效果如下: 这个效果体验很好 ...