一、事物的概念

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

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

  事物的特性:事务必须服从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. 将svg文件化成字体图标的步骤

     一 前提摘要     有一个活就是按照需求在现有的项目中新增几个项目和修改几个项目,是很简单的,但当中遇到了一个小问题,就是tabs中图标选中和被选中的颜色问题,如果是新开发的,目前掌握的有两种办法 ...

  2. java~lombok里的Builder注解

    lombok注解在java进行编译时进行代码的构建,对于java对象的创建工作它可以更优雅,不需要写多余的重复的代码,这对于JAVA开发人员是很重要的,在出现lombok之后,对象的创建工作更提供Bu ...

  3. Unity 虚拟摇杆的实现

    一般地,虚拟摇杆是放在UI层的. 所以先在Canvas建立一个空对象(这里被命名成MoveController),再在空对象里面放一个作为摇杆图片的Image. 然后通过覆盖重写UnityEngine ...

  4. 浅谈Promise

    学习过JavaScript的人都知道,JavaScript是单线程作业,这样会有一个很大的缺陷,所有的Ajax,浏览器事件等,都是通过异步去完成.所谓的同步和异步最大的区别无非就是在于同步会阻塞后续代 ...

  5. 粮草先行——Android折叠屏开发技术点(一)

    最近有关折叠屏产品的新闻层出不穷,各家手机厂商也分别慢慢地亮出了自家的产品.然而市场上的一些APP仍然没有很好地适配这样的设备,显示不正常和应用重启的状况时有发生.因此,我会用接下来的几篇文章来点出有 ...

  6. Java 合并、拆分PDF文档

    处理PDF文档时,我们可以通过合并的方式,来任意组几个不同的PDF文件或者通过拆分将一个文件分解成多个子文件,这样的好处是对文档的存储.管理很方便.下面将通过Java程序代码介绍具体的PDF合并.拆分 ...

  7. eclipse导入java工程

    1)File下的import选项 2)点击General,选择Existing Projects into Workspace,点击next 3)点击Browse,在弹出的窗口中选择导入工程所在的文件 ...

  8. es6之字符串添加的东西

    在es6里边对字符串添加了一些东西! 字符串模板(非常友善) 相信大家之前都遇到过万恶的字符串拼接,真是噩梦,不过之后有了字符串模板之后,再也不用担心字符串拼接会乱了... 之前的字符串拼接 let ...

  9. 在 Angular 8 中,我们可以期待些什么

    转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 本文由葡萄城翻译并发布 --- Angular 作为一款优秀的前端框架,自诞生之日起,就致力于面向前端开发者 ...

  10. Redmine入门-安装

    Redmine提供了两种方式安装,如果仅仅只是使用Redmine,建议采用一键安装的方式,快捷方便.如果需要做二次开发或者更多的个性化处理,可以采用源码安装方式,下面分别介绍两种安装方式. ----- ...