CRUD也有他的道道(二)

前面已经起了个头,今天接着往下找CRUD的道道,都是日常的小事,但道就隐藏在其中!

入参设计

做Java,正常来讲,大部分都是与业务功能打交道,真正用Java搞技术类的项目并不是没有,但占比一定少,实际工作中,遇到一些高并发,秒杀类的都算是比较有技术含量了,这也就造成了了一种假象,即:业务功能开发就不需要设计,就不用设计。其实不然,设计理念无处不在,业务功能开发亦需设计,排除功能本身设计不说,单拿个入参设计就有自己的一些门道!

先来两个接口设计:

java 复制代码
// 设计一:
public BaseResult create(UserRequest request);

public BaseResult update(UserRequest request);
java 复制代码
// 设计二:
public BaseResult create(UserRequest request);

public BaseResult update(UserUpdateRequest request);

以上两组接口设计哪个更优?显然是后者,但实际工作中,用前者的不在少数。从开发角度看,特别是0-1,最开始写下这个代码的开发来看,本身可能并没有什么问题,两个对象甚至属性完全相同,使用同一个Bean就很自然了,但这为后面的开发埋下了隐患,当遇到变更时,该不该调整 UserRequest,因为增加属性,可能对 update 方法没有用,而后面继续维护的人会疑惑 update 中没有用的属性,每次做处理都要特别小心。这明显违背了单一职责原则这一最基本的设计原则

示例还比较明显,容易区分,实际业务中,往往是不同接口用了同一个入参对象,但不一定是 create update 这种比较明显区别的情况,而是类似这种 updateByXX(UserUpdateRequest request) updateByBB(UserUpdateRequest request),但其同样属于第一种设计

职责越清晰,越明确,变更时就越方便,只需要关心自己接口的入参,而不需要考虑对其他接口的影响。这就是一种接口稳定,易于维护的表现!

DupicateKeyException

数据库的异常很多,为什么单单要讲这个异常,因为这个异常他不仅是异常,还参与了一些重要功能的设计。

并发插入这个问题,在小规模的系统里,其实并算是一个问题,但在大流量,高吞吐量的系统里,确实存在这样的情况,那么如何处理并发写,就显得尤为重要。

最容易想到的方案就是在写之前先查一把,确认没有数据再写入,或者用 Redis 锁,前者其实存在一些问题,毕竟竞态条件本身就是线程不安全的,所以不能完全阻止,少部分情况是有效的,后者基本可以避免,但多了一次redis操作,也是有点不够干脆利落!

那么采用数据库天然自带的机制,从业务代码层面就显得非常干净,在条件允许的情况下,捕获这种异常并加以处理,将非常有益于代码的维护!

redis 锁的方案在最近一些年比较常见,可能是这锁的成本确实不高吧。
当然能够使用这个方案的,也有一定的前提条件,须有唯一索引,否则确实不行

一般我们这么做:

java 复制代码
        try {
            Long impact = xxxDAO.insert(obj);
            if (impact == null || impact.intValue() <= 0) {
                logger.error("xxx异常,obj={}", obj);
                throw new XXXRuntimeException(...); // 这里自定义异常,看项目情况做,不便细说
            }
        } catch (DuplicateKeyException e) {
            logger.error("xxx异常,xx健重复,obj={}", obj);
            throw new XXXRuntimeException(); // 同上
        }

这样即使存在并发,也会随异常抛出,真正入库的肯定只会有一条记录。当然异常我默认大家都是有统一的方式处理的,不必与示例一样。

相关推荐
颜淡慕潇2 小时前
深度解析官方 Spring Boot 稳定版本及 JDK 配套策略
java·后端·架构
Victor3562 小时前
Hibernate(28)Hibernate的级联操作是什么?
后端
Victor3562 小时前
Hibernate(27)Hibernate的查询策略是什么?
后端
superman超哥3 小时前
Rust 内部可变性模式:突破借用规则的受控机制
开发语言·后端·rust·rust内部可变性·借用规则·受控机制
柒.梧.4 小时前
Spring核心知识全解析:从入门实战到进阶
java·后端·spring
乌日尼乐4 小时前
【Java基础整理】Java字符串处理,String、StringBuffer、StringBuilder
java·后端
qwepoilkjasd4 小时前
DMC发送M-SEARCH请求,DMR响应流程
后端
心在飞扬4 小时前
langchain学习总结:Python + OpenAI 原生 SDK 实现记忆功能
后端
张志鹏PHP全栈4 小时前
Solidity智能合约快速入门
后端
ihgry4 小时前
SpringCloud_Nacos
后端