1.问题情境
在开发中,前端不可避免的要捕获后台的各种非数据库的信息,比如各种违规提示等,其中有一种信息回显得方式是通过抛出异常,全局捕获异常的方式。
而通常操作日志或审计流水需要将操作失败的情况作为数据加入数据库中,但是为了回显信息就需要抛出异常,但是这和数据入库是相互矛盾的。
XXXXService.insert(Demo);
throw new RunTimeException("数据不合法,请检查后重新输入");
2.问题分析
事务有一个特性叫原子性,简单地说当一段代码有多条操作时,全部成功才会最终执行,只要有一部出错就回全部作废,也就是事务回滚。而手抛的异常就是这段代码出现的问题,一旦异常出现,所有操作全部作废。
3.解决方案
第一种方案是改变信息回显得方式,但这是整个架构公用的回显,一般情况不可取。
既然问题事务控制造成的,不妨从事务中入手。而当前项目,事务多由连接池整体把控。那么思路就来了,不如把入库操作单独提取成一个由自己独立控制的事务,摆脱连接池的束缚?
最尴尬的地方是怎么做?若再引入一个连接池,资源消耗大,冲突不易维护。不过归根结底,连接池也是一个封装的工具,为什么不自定义一个本地轻量连接供自己使用呢?而最常用的MyBatis底层封装了JDBD,旧时代JDBC对数据库的连接本来就是自己写的。
于是,方案来了:返璞归真,jdbc自定义链接独立事务摆脱冲突。
DriverClass.forName(com.mysql.jdbc.cj.Driver);
Connection conn=DriverManager.getConnection(url,username,password);