事务传播机制/数据库异常解析——2016-8-13分享总结

一. 事务的传播机制/required 跟 required new 的使用与区别

基础回顾

1.1 事务的隔离级别

  ISOLATION_READ_UNCOMMITTED(读未提交)

  ISOLATION_READ_COMMITTED(读已提交)

  ISOLATION_REPEATABLE_READ(可重复读)

  ISOLATION_SERIALIZABLE(序列化)    

  ISOLATION_DEFAULT(使用数据库默认隔离级别)

1.2 脏读,不可重复读以及幻读

  脏读:一个事务读取到另一事务未提交的更新新据。

  不可重复读:在同一事务中,多次读取同一数据返回的结果有所不同。换句话说就是,后续读取可以读到另一事务已提交的更新数据。

  幻读:事务1正常查询一次,之后事务2插入满足事务1查询条件的新行,再次用事务1查询,得到多出来的数据。

1.3 事务的传播属性

  PROPAGATION_REQUIRED:  支持当前事务,没有则新建

  PROPAGATION_REQUIRESNEW:  新建事务,如果当前存在事务,把当前事务挂起

  PROPAGATION_SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行

  PROPAGATION_MANDATORY:支持当前事务,如果当前没有事务,就抛出异常

  PROPAGATION_NOT_SUPPORTED:以非事务方式执行,如果当前存在事务,就把当前事务挂起。也就是说业务方法不需要事务

  PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。也就是说业务方法绝对不能在事务范围内执行

  PROPAGATION_NESTED:如果一个活动的事务存在,则运行在一个嵌套的事务中。 如果没有活动事务, 则按REQUIRED属性执行  

二. 事务的回滚及传播机制总结

  1. 首先要注意的是 spring 的默认回滚,roll-back = “runtimeException”,即 spring 只回滚接收到的运行时异常,对于其他异常则不回滚;

  源码解析:

/*** Handle a throwable, completing the transaction.* We may commit or roll back, depending on the configuration.* @param txInfo information about the current transaction* @param ex throwable encountered*/protected void completeTransactionAfterThrowing(TransactionInfo txInfo, Throwable ex) {if (txInfo != null && txInfo.hasTransaction()) {if (logger.isTraceEnabled()) {logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() +"] after exception: " + ex);}if (txInfo.transactionAttribute.rollbackOn(ex)) {try {txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());}catch (TransactionSystemException ex2) {logger.error("Application exception overridden by rollback exception", ex);ex2.initApplicationException(ex);throw ex2;}
...

  注意上述有一段是 txInfo.transactionAttribute.rollbackOn(ex) 方法,跟进此方法:

/*** The default behavior is as with EJB: rollback on unchecked exception.* Additionally attempt to rollback on Error.* <p>This is consistent with TransactionTemplate's default behavior.*/public boolean rollbackOn(Throwable ex) {return (ex instanceof RuntimeException || ex instanceof Error);}

  所以,默认不修改的话,只回滚 RuntimeException 或者 Error

  2. 对此我们可以针对性的添加需要回滚的策略,或者直接显示设置 roll-back = “Exception”,即回滚所有异常;

  3. 需要注意的是:普通情况下,如果异常被 try-catch 处理了,并为进一步抛出异常,那么由于 spring 并未接受到异常, 所以也不会回滚;

   本周讨论补充知识:

  4. 异常分为 应用层抛出 的异常,以及 数据库 的异常,如果是前者,可以正常应用 spring 的事务传播规则,如果是后者,那么一旦发生,数据库端就已经放弃事务,也就没有回滚一说();

  例: int 10/0 为应用层的异常,可以正常回滚; insert 提交一个已存在的 唯一字段,那么数据库会报错,由于事务本身也是由 spring 告之数据库处理,这种情况下,由于 数据库已经放弃事务,那么 spring 层面也不能进行事务回滚;

  5. 正常情况下不会出现一个接口的 bean 进行嵌套调用,如果有,该情况下,由于代理类不再使用 spring 动态代理中的接口实现的方式,而是采用 cglib 的继承实现方式,同样也会导致传播失效;

  6. 事务的传播机制较为常用的为:required,required-new,support。讨论结果为 required-new 跟 required 相比,使用应较为谨慎,原因:同一事务粒度更细更可控,同时也能避免 嵌套事务 可能导致的复杂情况,当然,具体情况需要根据具体业务来定,比如本次讨论中的项目,由于每一次操作的对象都要及时被可能存在的另一进程知悉,这种情况下需要 required-new 来实时开启事务告之其他进程;

  查询总结过程中发现的其它知识点

  1. 注意的小点,MySQL 中 InnoDB 支持事务,MyIsam 并不支持事务;

  2. spring 已经提供了异常处理机制,其基类为 DataAccessException ,它是 RuntimeExcption 的一个子类,据此可以知道,所有从 数据库返回的异常,都会被 spring 处理后 归属于 RuntimeException 中,其体系如下:

  

2. 在 org.springframework.jdbc.support包下有sql-error-codes.xml文件,里面预定义了一些错误代码和信息,其 bean 为 HSQL,在 第8行,我们可以发现重复插入的 code 为 -104;

  bean id="HSQL" class="org.springframework.jdbc.support.SQLErrorCodes"    property name="databaseProductName"     valueHSQL Database Engine/value     /property     property name="badSqlGrammarCodes"     value-22,-28/value     /property     property name="duplicateKeyCodes"     value-104/value     /property     property name="dataIntegrityViolationCodes"     value-9/value     /property     property name="dataAccessResourceFailureCodes"     value-80/value     /property     /bean     

  3. 此外,我们可以知道发散性的看,我们完全可以自定义数据库异常的信息,方法如下:

  3.1 重新新建一个sql-error-codes.xml代码,并将它放到类路径的根目录下,这样Spring会发现它并使用我们自定义的文件。同时HSQL的bean的名称不要改,并将useSqlStateForTranslation置为false,就可以使用我们自己定义的异常类;

bean id="HSQL" class="org.springframework.jdbc.support.SQLErrorCodes"     property name="databaseProductName" value="HSQL Database Engine" /     property name="useSqlStateForTranslation" value="false" /     property name="customTranslations"     list     ref local="vehicleDuplicateKeyTranslation" /     /list     /property     /bean     
bean id="vehicleDuplicateKeyTranslation"     class="org.springframework.jdbc.support.CustomSQLErrorCodesTranslation"     property name="errorCodes" value="-104" /     property name="exceptionClass" value="org.ourpioneer.vehicle.exception.VehicleDuplicateKeyException" /     /bean 

  3.2 可以看到结果,控制台所打印的异常类型为我们自己定义的异常类型;

  3.3 除此之外,还可以实现SQLExceptionTranslator接口,并在JDBC模板中注入其实例来实现异常控制

   1. package org.ourpioneer.vehicle.exception;      2. import java.sql.SQLException;      3. import org.springframework.dao.DataAccessException;      4. import org.springframework.jdbc.UncategorizedSQLException;      5. import org.springframework.jdbc.support.SQLExceptionTranslator;      6. public class VehicleDuplicateKeyTranslator implements SQLExceptionTranslator {      7.     public DataAccessException translate(String task, String sql,      8.             SQLException ex) {      9.         if (task == null) {      10.             task = "";      11.         }      12.         if (sql == null) {      13.         }      14.         if (ex.getErrorCode() == -104) {      15.             return new VehicleDuplicateKeyException(buildMessage(task, sql, ex));      16.         } else {      17.             return new UncategorizedSQLException(task, sql, ex);      18.         }      19.     }      20.     private String buildMessage(String task, String sql, SQLException ex) {      21.         return "数据库操作异常:" + task + "; SQL [" + sql + "]; " + ex.getMessage();      22.     }      23. } 

  3.4 translate方法有三个参数,task表示当前操作要进行的任务是什么,sql就是执行的sql语句,ex表示SQLException,我们可以从中获取异常信息,其处理代码仅仅捕捉了错误码为-104(HSQL数据库)的错误,其余的配置信息可以根据需要来自行添加。之后要在Spring中重新配置它们:

   1. bean id="vehicleDuplicateKeyTranslator"     2. class="org.ourpioneer.vehicle.exception.VehicleDuplicateKeyTranslator"/bean     3. bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"     4.     property name="exceptionTranslator" ref="vehicleDuplicateKeyTranslator" /     5.     property name="dataSource" ref="dataSource" /     6. /bean     7. bean id="vehicleDAO" class="org.ourpioneer.vehicle.dao.VehicleDAOImpl"     8.     property name="jdbcTemplate" ref="jdbcTemplate" /     9. /bean 

  3.5 测试结果

 

三. 总结

  其实之前对事务的理解是比较基础的,经过周六的交流和学习,才对事务有了略深一层的理解,但同时也愈发觉得事务的博大精深应远不止于此,本文大部分都是结合各位?同事的理解和网上的一些资料整理的文章,所以本文作用更多的督促自己的学习进步,希望以后自己能不断的吸收,整理和提炼知识?。

 

参考文献:

mysql隔离级别及事务传播:https://gist.github.com/JagoWang/4555317

mysql事务管理及spring声明式事务中主动异常抛出使数据库回滚:http://www.cnblogs.com/wanglonghai/p/4866512.html

Spring访问数据库异常的处理方法:http://kb.cnblogs.com/page/89216/

转载于:https://www.cnblogs.com/Mr-Persist/p/5773314.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/254677.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

console类详细解释

console类详细解释 微软链接https://docs.microsoft.com/zh-cn/dotnet/api/system.console?viewnetframework-4.8 C#中没有标准输入输出关键字&#xff0c;要调用console类下的方法。 练习与解释代码 using System; using System.Collections.Generic; using System.Linq; …

VC下调用x264进行视频编码,

4.X264.c中,h x264_encoder_open( param ) )是用来复制参数并验证参数的有效性,在CCS下应该是不需要验证参数的(参数都是在程序中设置好的),因此此处只作复制参数param和初始化X264_T h的操作.(VC下程序修改记录080106下午)修改COMMON.C中的void x264_param_default( x264_…

UploadRTOS.exe

UploadRTOS.exe类似于一个启动并为VxWin运行做准备的工具程序。VxWin安装之后&#xff0c;可以使用 上传工具程序 启动实时操作系统。 利用命令行参数,您可以使它执行不同的功能。该 上传工具程序 包含两个文件: UploadRTOS.exe (命令行程序) UploadR…

20155307 2016-2017 《Java程序设计》第三次实验报告

&#xff08;一&#xff09;敏捷开发与XP 敏捷开发是一种以人为核心、迭代、循序渐进的开发方法。“敏捷流程”是一系列价值观和方法论的集合。从2001年开始&#xff0c;一些软件界的专家开始倡导“敏捷”的价值观和流程&#xff0c;他们肯定了流行做法的价值&#xff0c;但是强…

ElasticSearch创建、修改、获取、删除、索引Indice mapping和Index Template案例

为什么80%的码农都做不了架构师&#xff1f;>>> The best elasticsearch highlevel java rest api-----bboss ElasticSearch客户端框架bboss的ClientInterface 接口提供了创建/修改、获取、删除索引Indice和IndexTemplate的方法&#xff0c;本文举例说明其使用方法…

ASCII码与string的相互转换

ASCII码与string的相互转换 思路&#xff1a; 1&#xff09;ASCII码转string&#xff1a;把字符&#xff08;串&#xff09;直接转换为int类型&#xff0c;即可得到ASCII码&#xff1b; 2&#xff09;string转ASCII码&#xff1a;将数字转换为字符串转出&#xff1b; {//将字…

X264代码中一些参数的意义

Main&#xff08;int argc&#xff0c;char *argv[]&#xff09;; 为了方便起见&#xff0c;不妨改写为&#xff1a; Main(void){ ...... intargc5; char*argv[]{ "main","-o","test.264","foreman.yuv","352x288" }; …

spring mvc注解@RequestMapping

1、url路径映射 基本功能 2、窄化请求映射 根路径子路径 注意setViewName的路径。 3、限制http请求方法 get和 post 如果是get 转载于:https://www.cnblogs.com/jway1101/p/5773923.html

Start application automatically during controller boot-up

&#xfeff;&#xfeff; Tip English •German Start application automatically during controller boot-up Description It is possible to start any program automatically during the boot-up procedure of the KR C4 controller. Precondition •User group “Exper…

C#using static

平常用法&#xff1a; using 命名空间&#xff1b; using System; Console.WriteLine("Hello&#xff0c;World&#xff01;");using static用法&#xff1a; C#6中支持这种写法&#xff0c;这样定义后可以可以访问类的静态成员 WriteLine是Console类的静态函数&am…

redis数据迁移

一&#xff1a;AOF方式 需求&#xff1a; 一个没有数据的redis。 清空redis数据方法 bash> echo "keys *" | redis-cli --raw -p 6378 |sed -r s/(.*)/redis-cli --raw -p 6378 del \1 /g |bash 1.备份 bash> redis-cli --raw -p 6378 redis> config get di…

阿里云OSS 上传文件SDK

Aliyun OSS SDK for C# 上传文件 另外&#xff1a;查找的其他实现C#上传文件功能例子&#xff1a; 1、WPF用流的方式上传/显示/下载图片文件(保存在数据库) &#xff08;文末有案例下载链接&#xff09; 2、WPF中利用WebClient向服务器上传文件 3、C#文件上传的简单实现 4、C#实…

关于level_idc和Profile_IDC的解释

2010-01-21 15:51:40| 分类&#xff1a; windows mobile开 |字号 订阅 Description: Set bitstream Profile IDC. Default is 88. Note: Some profiles cannot support certain features. See MPEG-4 AVC for supported features for each profile. Reference software may…

老婆的驾照要下来了,形容下我此刻的心情

&#xfeff;&#xfeff; 老婆的驾照要下来了&#xff0c;形容下我此刻的心情&#xff1a; 路上遇到的女人&#xff0c;大部分是不用眼睛和脑子开车的&#xff0c;完全是凭自己的感觉开车。凡是看到前车奇慢、路口犹豫不决、不打灯缓慢变线、不该…

ADO.NET改进防注入

static void Main1(string[] args) { //用户输入一个需要查询的条件 car表 Console.WriteLine("请输入"); string code Console.ReadLine(); SqlConnection conn new SqlConnection("server.;databasemydb;usersa;pwd100867"); SqlCommand cmd conn.Crea…

poj 2139

Floyd-Warshall模板题&#xff0c;我才刚学最短路。。。。 #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> using namespace std; const int maxn30050; int d[maxn][maxn]; int v,m,n; int a[maxn]; const int inf0…

C#使用了未赋值的局部变量

错误原因&#xff1a; 我们先看下例子&#xff1a; int A; Console.WriteLine("数字&#xff1a;{0:d}", A);//在控制台输出文本这时提示错误&#xff1a;错误 1 使用了未赋值的局部变量“A” 原因是C#在使用变量前必须要进行初始化。 解决 解决方案有两个 1、在…

EtherCAT伺服驱动器-如何选择硬件开发方案

&#xfeff;&#xfeff;EtherCAT伺服驱动器-如何选择硬件开发方案

Codevs 1689 建造高塔

1689 建造高塔时间限制: 1 s空间限制: 128000 KB题目等级 : **钻石 Diamond** 题目描述 Description n有n种石块&#xff0c;石块能无限供应。每种石块都是长方体&#xff0c;其中第i种石块的长、宽、高分别为li、wi、hi。石块可以旋转&#xff0c;使得其中两维成为长度和宽度&…

windows环境下OpenLDAP安装与客户端连接配置

2019独角兽企业重金招聘Python工程师标准>>> 1.下载安装OpenLDAP版本 C:\Users\Administrator>slapd -V OpenLDAP 2.4.42 Standalone LDAP Server (slapd) 2.安装过程中&#xff0c;全部用默认的操作执行即可。 3.修改OpenLDAP文件如下&#xff1a; # MDB Backen…