首页 文章 精选 留言 我的

精选列表

搜索[多分片],共10000篇文章
优秀的个人博客,低调大师

Scala 3.0.0-M3 发布,多范式编程语言

Scala 3.0.0-M3 已经发布。 作为“开发人员预览版”,Scala 3.0.0-M3 承载着收集 Scala 开发人员和用户反馈的任务。如果在 2020 年 12 月 18 日至 2021 年 1 月中旬之间未出现重大问题,Scala 中心团队和社区贡献者将继续使用相同的 API 在 2021 年 1 月底发布 Scala 3-RC1 版本。 更新细节 语言特性 given 语句中移除 as#10538 在模式中移除 as#10565 修复#10484: 切换回旧的上下文函数闭包语法#10487 添加可匹配特征#10670 元编程 添加 Expr.asTerm#10694 移除Expr.StringContext.unapply#10675 移除 reflect.LambdaType#10548 ...... 详情查看Scala 3.0.0-M3 版本细节 延伸阅读 Scala 3 版本规划

优秀的个人博客,低调大师

精选VS Code高频插件,让你多陪陪npy!

1.TODO Highlight 高亮显示你的 TODO、FIXME,支持自定义关键字和外观,可以起到良好的提示作用。 2.Vetur + Prettier + ESLint 解决冲突后配合使用完美格式化代码,能交给机器做的一定要学会偷懒。 3.Highlight Matching Tag 实时高亮匹配标签,不用在 HTML 中眼花缭乱的找标签了。 4.javascript console utils 快速生成 console.log() ,调试利器,妈妈再也不用担心你的指关节。 5.Code Runner 一键运行代码,支持很多语言。 6.Comment Translate 插件使用 Google Translate API 翻译注释,功能强大,在看开源项目源代码的时候很有用(英文好的话请忽略)。 7.Image preview 图片预览,可以在代码行号左侧槽位(或hover时)预览图片。 8.Version Lens 显示包版本信息,在 package.json 中显示包最新版本等信息。 9.vscode-pigments 实时显示css, sass, jsx中的颜色。 10.Auto Close Tag 自动补全标签。 11.Auto Rename Tag 同步修改标签。 12.Bracket Pair Colorizer 不同颜色高亮显示匹配的括号。 13.Code Spell Checker 单词拼写检查。 14.WakaTime 编程时间记录工具,在它的官网 Dashboard 中以图形化方式展示你的编程时间,让你更清晰的掌握你的时间都去哪了。 最后 关注公众号【前端宇宙】,每日获取好文推荐 添加微信,入群交流 本文分享自微信公众号 - 前端宇宙(gh_8184da923ced)。如有侵权,请联系 support@oschina.cn 删除。本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

优秀的个人博客,低调大师

一个@Transaction哪里来这么多坑?

点击蓝色“程序员DMZ”关注我哟 好看记得加个“星标”哈! 前言 在之前的文章中已经对Spring中的事务做了详细的分析了,这篇文章我们来聊一聊平常工作时使用事务可能出现的一些问题(本文主要针对使用@Transactional进行事务管理的方式进行讨论)以及对应的解决方案 事务失效 事务回滚相关问题 读写分离跟事务结合使用时的问题 事务失效 事务失效我们一般要从两个方面排查问题 数据库层面 数据库层面,数据库使用的存储引擎是否支持事务?默认情况下MySQL数据库使用的是Innodb存储引擎(5.5版本之后),它是支持事务的,但是如果你的表特地修改了存储引擎,例如,你通过下面的语句修改了表使用的存储引擎为MyISAM,而MyISAM又是不支持事务的 altertabletable_nameengine=myisam; 这样就会出现“事务失效”的问题了 「解决方案」:修改存储引擎为Innodb。 业务代码层面 业务层面的代码是否有问题,这就有很多种可能了 我们要使用Spring的声明式事务,那么需要执行事务的Bean是否已经交由了Spring管理?在代码中的体现就是类上是否有 @Service、 Component等一系列注解 「解决方案」:将Bean交由Spring进行管理(添加@Service注解) @Transactional注解是否被放在了合适的位置。在上篇文章中我们对Spring中事务失效的原理做了详细的分析,其中也分析了Spring内部是如何解析 @Transactional注解的,我们稍微回顾下代码: 注解解析 ❝ 代码位于:AbstractFallbackTransactionAttributeSource#computeTransactionAttribute中 ❞ 也就是说,默认情况下你无法使用@Transactional对一个非public的方法进行事务管理 「解决方案」:修改需要事务管理的方法为public。 出现了自调用。什么是自调用呢?我们看个例子 @ServicepublicclassDmzService{publicvoidsaveAB(Aa,Bb){saveA(a);saveB(b);}@TransactionalpublicvoidsaveA(Aa){dao.saveA(a);}@TransactionalpublicvoidsaveB(Bb){dao.saveB(a);}} 上面三个方法都在同一个类DmzService中,其中saveAB方法中调用了本类中的saveA跟saveB方法,这就是自调用。在上面的例子中saveA跟saveB上的事务会失效 那么自调用为什么会导致事务失效呢?我们知道Spring中事务的实现是依赖于AOP的,当容器在创建dmzService这个Bean时,发现这个类中存在了被@Transactional标注的方法(修饰符为public)那么就需要为这个类创建一个代理对象并放入到容器中,创建的代理对象等价于下面这个类 publicclassDmzServiceProxy{privateDmzServicedmzService;publicDmzServiceProxy(DmzServicedmzService){this.dmzService=dmzService;}publicvoidsaveAB(Aa,Bb){dmzService.saveAB(a,b);}publicvoidsaveA(Aa){try{//开启事务startTransaction();dmzService.saveA(a);}catch(Exceptione){//出现异常回滚事务rollbackTransaction();}//提交事务commitTransaction();}publicvoidsaveB(Bb){try{//开启事务startTransaction();dmzService.saveB(b);}catch(Exceptione){//出现异常回滚事务rollbackTransaction();}//提交事务commitTransaction();}} 上面是一段伪代码,通过startTransaction、rollbackTransaction、commitTransaction这三个方法模拟代理类实现的逻辑。因为目标类DmzService中的saveA跟saveB方法上存在@Transactional注解,所以会对这两个方法进行拦截并嵌入事务管理的逻辑,同时saveAB方法上没有@Transactional,相当于代理类直接调用了目标类中的方法。 我们会发现当通过代理类调用saveAB时整个方法的调用链如下: 实际上我们在调用saveA跟saveB时调用的是目标类中的方法,这种清空下,事务当然会失效。 常见的自调用导致的事务失效还有一个例子,如下: @ServicepublicclassDmzService{@Transactionalpublicvoidsave(Aa,Bb){saveB(b);}@Transactional(propagation=Propagation.REQUIRES_NEW)publicvoidsaveB(Bb){dao.saveB(a);}} 当我们调用save方法时,我们预期的执行流程是这样的 也就是说两个事务之间互不干扰,每个事务都有自己的开启、回滚、提交操作。 但根据之前的分析我们知道,实际上在调用saveB方法时,是直接调用的目标类中的saveB方法,在saveB方法前后并不会有事务的开启或者提交、回滚等操作,实际的流程是下面这样的 由于saveB方法实际上是由dmzService也就是目标类自己调用的,所以在saveB方法的前后并不会执行事务的相关操作。这也是自调用带来问题的根本原因:「自调用时,调用的是目标类中的方法而不是代理类中的方法」 「解决方案」: 自己注入自己,然后显示的调用,例如: @ServicepublicclassDmzService{//自己注入自己@AutowiredDmzServicedmzService;@Transactionalpublicvoidsave(Aa,Bb){dmzService.saveB(b);}@Transactional(propagation=Propagation.REQUIRES_NEW)publicvoidsaveB(Bb){dao.saveB(a);}} 这种方案看起来不是很优雅 利用AopContext,如下: @ServicepublicclassDmzService{@Transactionalpublicvoidsave(Aa,Bb){((DmzService)AopContext.currentProxy()).saveB(b);}@Transactional(propagation=Propagation.REQUIRES_NEW)publicvoidsaveB(Bb){dao.saveB(a);}} ❝ 使用上面这种解决方案需要注意的是,需要在配置类上新增一个配置 //exposeProxy=true代表将代理类放入到线程上下文中,默认是false@EnableAspectJAutoProxy(exposeProxy=true) ❞ 个人比较喜欢的是第二种方式 这里我们做个来做个小总结 总结 一图胜千言 事务失效的原因 事务回滚相关问题 回滚相关的问题可以被总结为两句话 想回滚的时候事务却提交了 想提交的时候被标记成只能回滚了(rollback only) 先看第一种情况:「想回滚的时候事务却提交了」。这种情况往往是程序员对Spring中事务的rollbackFor属性不够了解导致的。 ❝ Spring默认抛出了未检查unchecked异常(继承自 RuntimeException 的异常)或者 Error才回滚事务;其他异常不会触发回滚事务,已经执行的SQL会提交掉。如果在事务中抛出其他类型的异常,但却期望 Spring 能够回滚事务,就需要指定rollbackFor属性。 ❞ 对应代码其实我们上篇文章也分析过了,如下: 回滚代码 ❝ 以上代码位于:TransactionAspectSupport#completeTransactionAfterThrowing方法中 ❞ 默认情况下,只有出现RuntimeException或者Error才会回滚 publicbooleanrollbackOn(Throwableex){return(exinstanceofRuntimeException||exinstanceofError);} 所以,如果你想在出现了非RuntimeException或者Error时也回滚,请指定回滚时的异常,例如: @Transactional(rollbackFor=Exception.class) 第二种情况:「想提交的时候被标记成只能回滚了(rollback only)」。 对应的异常信息如下: Transactionrolledbackbecauseithasbeenmarkedasrollback-only 我们先来看个例子吧 @ServicepublicclassDmzService{@AutowiredIndexServiceindexService;@TransactionalpublicvoidtestRollbackOnly(){try{indexService.a();}catch(ClassNotFoundExceptione){System.out.println("catch");}}}@ServicepublicclassIndexService{@Transactional(rollbackFor=Exception.class)publicvoida()throwsClassNotFoundException{//......thrownewClassNotFoundException();}} 在上面这个例子中,DmzService的testRollbackOnly方法跟IndexService的a方法都开启了事务,并且事务的传播级别为required,所以当我们在testRollbackOnly中调用IndexService的a方法时这两个方法应当是共用的一个事务。按照这种思路,虽然IndexService的a方法抛出了异常,但是我们在testRollbackOnly将异常捕获了,那么这个事务应该是可以正常提交的,为什么会抛出异常呢? 如果你看过我之前的源码分析的文章应该知道,在处理回滚时有这么一段代码 rollBackOnly设置 在提交时又做了下面这个判断(这个方法我删掉了一些不重要的代码) commit_rollbackOnly 可以看到当提交时发现事务已经被标记为rollbackOnly后会进入回滚处理中,并且unexpected传入的为true。在处理回滚时又有下面这段代码 抛出异常 最后在这里抛出了这个异常。 ❝ 以上代码均位于AbstractPlatformTransactionManager中 ❞ 总结起来,「主要的原因就是因为内部事务回滚时将整个大事务做了一个rollbackOnly的标记」,所以即使我们在外部事务中catch了抛出的异常,整个事务仍然无法正常提交,并且如果你希望正常提交,Spring还会抛出一个异常。 「解决方案」: 这个解决方案要依赖业务而定,你要明确你想要的结果是什么 内部事务发生异常,外部事务catch异常后,内部事务自行回滚,不影响外部事务 ❝ 将内部事务的传播级别设置为nested/requires_new均可。在我们的例子中就是做如下修改: //@Transactional(rollbackFor=Exception.class,propagation=Propagation.REQUIRES_NEW)@Transactional(rollbackFor=Exception.class,propagation=Propagation.NESTED)publicvoida()throwsClassNotFoundException{//......thrownewClassNotFoundException();} ❞ 虽然这两者都能得到上面的结果,但是它们之间还是有不同的。当传播级别为requires_new时,两个事务完全没有联系,各自都有自己的事务管理机制(开启事务、关闭事务、回滚事务)。但是传播级别为nested时,实际上只存在一个事务,只是在调用a方法时设置了一个保存点,当a方法回滚时,实际上是回滚到保存点上,并且当外部事务提交时,内部事务才会提交,外部事务如果回滚,内部事务会跟着回滚。 内部事务发生异常时,外部事务catch异常后,内外两个事务都回滚,但是方法不抛出异常 ❝ @TransactionalpublicvoidtestRollbackOnly(){try{indexService.a();}catch(ClassNotFoundExceptione){//加上这句代码TransactionInterceptor.currentTransactionStatus().setRollbackOnly();}} ❞ 通过显示的设置事务的状态为RollbackOnly。这样当提交事务时会进入下面这段代码 显示回滚 最大的区别在于处理回滚时第二个参数传入的是false,这意味着回滚是回滚是预期之中的,所以在处理完回滚后并不会抛出异常。 读写分离跟事务结合使用时的问题 读写分离一般有两种实现方式 配置多数据源 依赖中间件,如 MyCat 如果是配置了多数据源的方式实现了读写分离,那么需要注意的是:「如果开启了一个读写事务,那么必须使用写节点」,「如果是一个只读事务,那么可以使用读节点」 如果是依赖于MyCat等中间件那么需要注意:「只要开启了事务,事务内的SQL都会使用写节点(依赖于具体中间件的实现,也有可能会允许使用读节点,具体策略需要自行跟DB团队确认)」 基于上面的结论,我们在使用事务时应该更加谨慎,在没有必要开启事务时尽量不要开启。 ❝ 一般我们会在配置文件配置某些约定的方法名字前缀开启不同的事务(或者不开启),但现在随着注解事务的流行,好多开发人员(或者架构师)搭建框架的时候在service类上加上了@Transactional注解,导致整个类都是开启事务的,这样严重影响数据库执行的效率,更重要的是开发人员不重视、或者不知道在查询类的方法上面自己加上@Transactional(propagation=Propagation.NOT_SUPPORTED)就会导致,所有的查询方法实际并没有走从库,导致主库压力过大。 ❞ 其次,关于如果没有对只读事务做优化的话(优化意味着将只读事务路由到读节点),那么@Transactional注解中的readOnly属性就应该要慎用。我们使用readOnly的原本目的是为了将事务标记为只读,这样当MySQL服务端检测到是一个只读事务后就可以做优化,少分配一些资源(例如:只读事务不需要回滚,所以不需要分配undo log段)。但是当配置了读写分离后,可能会可能会导致只读事务内所有的SQL都被路由到了主库,读写分离也就失去了意义。 总结 本文为事务专栏最后一篇啦!这篇文章主要是总结了工作中事务相关的常见问题,想让大家少走点弯路!希望大家可以认真读完哦,有什么问题可以直接在后台私信我或者加我微信! 这篇文章也是整个Spring系列的最后一篇文章,之后可能会出一篇源码阅读心得,跟大家聊聊如何学习源码。 另外今年也给自己定了个小目标,就是完成SSM框架源码的阅读。目前来说Spring是完成,接下来就是SpringMVC跟MyBatis。 在分析MyBatis前,会从JDBC源码出发,然后就是MyBatis对配置的解析、MyBatis执行流程、MyBatis的缓存、MyBatis的事务管理以及MyBatis的插件机制。 在学习SpringMVC前,会从TomCat出发,先讲清楚TomCat的原理,我们再来看SpringMVC。整个来说相比于Spring源码,我觉得应该不算特别难。 希望在这个过程中可以跟大家一起进步!!! 我叫DMZ,一个陪你一起慢慢进步的小菜鸟~! 往期精选 Spring事务源码分析专题(一)JdbcTemplate使用及源码分析 Spring事务源码分析专题(二)Mybatis的使用及跟Spring整合原理分析 Spring事务专题(三)事务的基本概念,Mysql事务处理原理 Spring事务专题(四)Spring中事务使用、抽象机制及模拟Spring事务实现 本文分享自微信公众号 - 程序员DMZ(programerDmz)。如有侵权,请联系 support@oschina.cn 删除。本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

优秀的个人博客,低调大师

DataGrip 2020.1 正式发布,多引擎数据库环境

DataGrip 2020.1 正式发布了,更新内容包括: 运行配置 运行脚本文件的配置 运行代码的配置 支持 utPLSQL 和 tSQLt Data editor 编辑器中的结果 地理检视器 [MongoDB] 数据过滤 导出选项 导出到 Excel 更好的可用性 文字资料检视器 连接性 [PostgreSQL] pg_pass 支持 [SQL Server] 域凭据支持 共享的 SSH 配置 查询控制台 更新预览 轻松导航到执行设置 日期时间注入 [MongoDB] 更好的编码帮助 导航和搜索 上下文数据源范围 结构搜索 文件处理 CSV 档案类型 附加目录 标记为纯文本​​​​​​​ 数据库树视图 用于创建用户和角色的用户界面 用于创建架构和数据库的 UI 更新说明:https://blog.jetbrains.com/datagrip/2020/04/06/datagrip-2020-1/

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册