使用事务注意事项事务是程序运行如果没有错误,会自动提交事物,如果程序运行发生异常,则会自动回滚。
如果使用了try捕获异常时.一定要在catch里面手动回滚。
事务手动回滚代码
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();声明事务实现
概述
管理建立在AOP之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,
在执行完目标方法之后根据执行情况提交或者回滚事务。声明式事务最大的优点就是不需要通过编程的方式管理事务,
这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明
(或通过基于@Transactional注解的方式),
便可以将事务规则应用到业务逻辑中。显然声明式事务管理要优于编程式事务管理,这正是spring倡导的非侵入式的开发方式。声明式事务管理使业务代码不受污染,一个普通的POJO对象,只要加上注解就可以获得完全的事务支持。和编程式事务相比,
声明式事务唯一不足地方是,后者的最细粒度只能作用到方法级别,无法做到像编程式事务那样可以作用到代码块级别。
但是即便有这样的需求,也存在很多变通的方法,比如,可以将需要进行事务管理的代码块独立为方法等等。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.learn</groupId><artifactId>demo</artifactId><version>0.0.1-SNAPSHOT</version><dependencies><!-- https://mvnrepository.com/artifact/javassist/javassist --><dependency><groupId>javassist</groupId><artifactId>javassist</artifactId><version>3.12.1.GA</version></dependency><!-- 引入Spring-AOP等相关Jar --><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>3.0.6.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>3.0.6.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>3.0.6.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-orm</artifactId><version>3.0.6.RELEASE</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjrt</artifactId><version>1.6.1</version></dependency><dependency><groupId>aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.5.3</version></dependency><dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>2.1_2</version></dependency><!-- https://mvnrepository.com/artifact/com.mchange/c3p0 --><dependency><groupId>com.mchange</groupId><artifactId>c3p0</artifactId><version>0.9.5.2</version></dependency><!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.37</version></dependency></dependencies></project>
<?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"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><!-- 这里表示扫包范围 因为我们是使用注解的,--><context:component-scan base-package="com.learn"></context:component-scan><!-- 这里表示开启事务的注解 你如果想要事务的话,你必须开启一个事务注解,--><aop:aspectj-autoproxy></aop:aspectj-autoproxy> <!-- 开启事物注解 --><!-- 1. 数据源对象: C3P0连接池 --><!-- 第一步我们加载C3P0数据源 DBCP和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://localhost:3306/day20"></property><property name="user" value="root"></property><property name="password" value="123456"></property></bean><!-- 2. JdbcTemplate工具类实例  --><!-- 这里要引用到我的数据源 --><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource"></property></bean><!-- 3.配置事务 --><bean id="dataSourceTransactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"></property></bean>
</beans>
package com.learn.service;public interface UserService {public void add();
}
package com.learn.service.impl;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;import com.learn.dao.UserDao;
import com.learn.service.UserService;
import com.learn.transaction.TransactionUtils;/*** 这就是编程式事务* * @author Leon.Sun**/
@Service
public class UserServiceImpl implements UserService {@Autowiredprivate TransactionUtils transactionUtils;@Autowiredprivate UserDao userDao;public void add() {/*** transactionStatus这样起名还是规范一点* */TransactionStatus transactionStatus = null;/*** 这里一定要try起来* 事务没问题才会提交* 有问题就会回滚* */try {/*** 开启事务*/transactionStatus = transactionUtils.begin();userDao.add("test001", 20);/*** 这个时候test001会不会提交到数据库里面去* 肯定不会的* 因为你的事务还没有提交* 我怎么可能到数据库里面查到呢* 是肯定不会到数据库里面去的* 因为你没有commit我怎么能到数据库里面查的到呢* 肯定是不会的* 我们打个断点看一下* 已经走完了* 有没有数据你们说* 是不是没有* 因为你没有提交到数据库里面去* 报错他就会走到catch里面去* 他就会把事务回滚* 数据库里面是不是没有* * 比如我们搞一个不报错的* 我再运行一遍* 只要你不提交肯定是查不到的* 到这里是不是查不到* 当transactionUtils.commit(transactionStatus)这段代码执行完毕的情况下* 你这两个数据都是可以查到的* 是不是提交了* 提交了之后test001和test002是不是都有了* 这就是事务的一个基本原理* 到时候我们结合AOP自己封装一个事务* * */System.out.println("开始报错了..........................");
//          int i = 1/0;System.out.println("####################################");userDao.add("test002", 21);/*** 提交事务* transactionStatus!=null这个是为了安全起见*/if(transactionStatus!=null) {             transactionUtils.commit(transactionStatus);}} catch (Exception e) {e.printStackTrace();/*** 异常我们最好这样子做* 如果发生异常的情况下* 走到这里一定要调用rollback* 回滚事务* transactionStatus!=null这个是为了安全起见*/if(transactionStatus!=null) {              transactionUtils.rollback(transactionStatus);}}}
}
package com.learn.transaction;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;/*** 我们今天讲手写事务* 我们要他的注解来实现事务* 注解其实都是封装起来的* 通过编程事务进行封装的* 编程事务(需要手动begin 手动回滚  手都提交)* 在这里我们要封装几个方法* 你们只要拿到ORM框架的接口就行了* 我们的数据源接口是哪一个* 就是dataSourceTransactionManager这个* 我们要拿到事务数据源* 然后进行控制事务* * 我们要把注入到Spring的容器里面去* 你们最好不要用单例的* 否则会产生线程安全问题的* * * * @author Leon.Sun**/
@Component
public class TransactionUtils {/*** 获取事务源* * 这里要注入一下@Autowired* */@Autowiredprivate DataSourceTransactionManager dataSourceTransactionManager;/*** 这个方法干嘛用的* 是不是开启事务* * * @return*/public TransactionStatus begin() {/*** 我们调用一下dataSourceTransactionManager* 我们先使用默认的传播级别DefaultTransactionAttribute* 没有学到传播级别* 不知道他里面怎么去用* 拿到了事务的一个状态* 记得要把事务的状态返回回去* 这里是开启一个事务* 我要提交事务怎么提交呢*/TransactionStatus transaction = dataSourceTransactionManager.getTransaction(new DefaultTransactionAttribute());return transaction;}/*** 这叫做提交事务* * 把状态传入进来* * * @param transaction*/public void commit(TransactionStatus transaction) {/*** 提价一个事务状态* */dataSourceTransactionManager.commit(transaction);}/*** 我们再写一个回滚事务* @param transaction*/public void rollback(TransactionStatus transaction) {dataSourceTransactionManager.rollback(transaction);}
}
package com.learn.test;import org.springframework.context.support.ClassPathXmlApplicationContext;import com.learn.service.UserService;public class Test001 {public static void main(String[] args) {ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");UserService userService = (UserService) applicationContext.getBean("userServiceImpl");userService.add();}}

手写spring编程事务相关推荐

  1. 手写 Spring 事务、IOC、DI 和 MVC

    Spring AOP 原理 什么是 AOP? AOP 即面向切面编程,利用 AOP 可以对业务进行解耦,提高重用性,提高开发效率 应用场景:日志记录,性能统计,安全控制,事务处理,异常处理 AOP 底 ...

  2. JAVA项目代码手写吗_一个老程序员是如何手写Spring MVC的

    见人爱的Spring已然不仅仅只是一个框架了.如今,Spring已然成为了一个生态.但深入了解Spring的却寥寥无几.这里,我带大家一起来看看,我是如何手写Spring的.我将结合对Spring十多 ...

  3. 记录一次阿里架构师全程手写Spring MVC

    人见人爱的Spring已然不仅仅只是一个框架了.如今,Spring已然成为了一个生态.但深入了解Spring的却寥寥无几.这里,我带大家一起来看看,我是如何手写Spring的.我将结合对Spring十 ...

  4. 十年java架构师分享:我是这样手写Spring的

    人见人爱的 Spring 已然不仅仅只是一个框架了.如今,Spring 已然成为了一个生态.但深入了解 Spring 的却寥寥无几.这里,我带大家一起来看看,我是如何手写 Spring 的.我将结合对 ...

  5. 从头开始实现一个小型spring框架——手写Spring之集成Tomcat服务器

    手写Spring之集成Tomcat与Servlet 写在前面 一.Web服务模型及servlet 1.1 Web服务器 1.2 请求流程 二.实现 三.小结 写在前面 最近学习了一下spring的相关 ...

  6. 手把手教你手写Spring框架

    手写spring准备工作: 新建一个maven工程: 架构 新建类: package com.spring;public class keweiqinApplicationContext {priva ...

  7. 手写Spring DI依赖注入,嘿,你的益达!

    手写DI 提前实例化单例Bean DI分析 DI的实现 构造参数依赖 一:定义分析 二:定义一个类BeanReference 三:BeanDefinition接口及其实现类 四:DefaultBean ...

  8. 手写 Spring MVC

    学习自<Spring 5核心原理与30个类手写实战>作者 Tom 老师 手写 Spring MVC 不多说,简历装 X 必备.不过练好还是需要求一定的思维能力. 一.整体思路 思路要熟练背 ...

  9. 05. 手写Spring核心框架

    目录 05 手写Spring核心框架 Pt1 手写IoC/DI Pt1.1 流程设计 Pt1.2 基础配置 application.properties pom.xml web.xml Pt1.3 注 ...

最新文章

  1. ios获取新数据要不要关_iOS开发之数据读写
  2. 相机内参_鱼眼相机标定模型
  3. 基于内存数据库的分布式数据库架构
  4. Linux下实现脚本监测特定进程占用内存情况
  5. 乐高(LEGO)在线购物店面剖析
  6. BugkuCTF-MISC题Pokergame
  7. Docker 部署clickhouse-server及添加用户配置密码
  8. c语言用switch字母判断星期几,c语言程序,输入年月日,判断这一天是这一年的第几天,同时判断这一天是星期几。(用switch语句)...
  9. python新手入门代码-Python 新手入门习题及代码
  10. 【莫队算法】URAL - 2080 - Wallet
  11. python创建变量revenue_Python pandas.DataFrame.le函数方法的使用
  12. VS2012更改/重置默认开发环境
  13. 如何获得大学教材的PDF版本?
  14. Rstudio中修改工作路径的三种方法
  15. Unity内置Shader解读9——Reflective/Bumped Diffuse
  16. python读文件-read_csv()-常用参数
  17. arm学习方法(转)
  18. ios sdk 穿山甲_Creator iOS接入穿山甲SDK
  19. 阿里云ECS学习资源
  20. 微信小程序开发需要什么前提条件?

热门文章

  1. 【WP8.1开发】RenderTargetBitmap类的特殊用途
  2. HDU 3123 GCC(同余模定理)
  3. 网络防火墙实战-基于pfsense(1)
  4. osgEarth用户手册
  5. ASP.NET 4新增功能(三) 对Web标准的支持和辅助功能的增强
  6. 【转】NuGet学习笔记(2)——使用图形化界面打包自己的类库
  7. 再谈软件测试-工作感悟
  8. Hive:表1inner join表2结果group by优化
  9. ITCAST-C# 委托
  10. mactex中文配置