一、模块审批流程设计原则经验:
场景:
1、通常在系统模块开发中,会涉及到数据审批流程流转,一般来说只要涉及到流程流转的业务,都会有流程的 起点 和 终点
2、有了流程起点和终点,所以就需要有一个 审批状态 字段来贯穿整个业务的主流程。每个审批状态下需要做不同的审批操作结果,所以还需要一个 审批结果 字段来记录。
3、审批结果主要是应对下一状态审批的时候需要判断上个状态节点的审批结果是什么,然后根据审批结果决定主流程审批状态的走向,例如:初审结果为通过,复审通过流程结束,初审结果为驳回,复审通过流程回到待初审的上一步。复审驳回,(无视初审结果)流程直接回到待初审
设计:
1、流程起点(审批状态):一般是指待审批、待审核、已提交、已申请、已上报等
2、流程中审批操作(审批结果):一般是审核通过、审核不通过、同意、不同意、通过、驳回、拒绝等
3、流程终点:一般是已结束、已完成、完成、终止等
二、微服务跨库CRUD操作
1、涉及到关联查询条件和分页的设计方案
方案1:因为是分布式跨数据库,所以无法直接表关联查询,但是在主界面查询列表中又需要用到从表的字段作为查询条件,并且还要分页。很显然关联查询不现实,那就用简单粗暴的方式,在从表字段中冗余需要作为查询条件的字段即可解决
说明:这种方式虽然很好的解决了跨库分页查询的问题,但需要注意如果冗余的字段值有改动,从表中冗余的条件字段也要同步改动
2、可以使用消息队列(MQ)实现跨库数据表同步。在库A表中冗余库B表中的相关字段,如果库B表信息更新后,向队列发送一条消息,库A服务监听消费即可根据条件来同步冗余的相关字段
三、如何合理开发包含复选框按钮的业务功能?(也适合一对多的数据提交保存场景)
1、第一次保存数据:这时候处理比较简单,直接遍历新增到复选框信息的从表中就可以了
2、更新数据:
方案一:删除主数据下所有已保存的复选框信息,然后重新写入新提交的复选框信息
方案二:先正常遍历处理当前提交的这批复选框信息,该新增新增、该修改修改,处理完成后,取出当前这批复选框的Id集合,然后删除当前主信息下除当前这批复选框的Id集合之外的复选框信息就Ok了,条件控制 delete from t_chekbox where bId=主信息Id and id not in (处理后当前这批复选框的Id集合)
3、如果是以逗号分隔的方式保存在主表字段中,这就容易的多,正常分隔保存即可
四、sql脚本中 exist 用法详解
1、exists:顾名思义,当前主查询的数据存在 exists() 子查询条件结果中
2、not exists():顾名思义,当前主查询的数据不存在 not exists() 子查询结果中,与 exists() 相反
3、使用案例如下:
select
sab.*
from sub_account_balance sab
where 1 = 1
and sab.deleted = 0
and sab.account_no = #{accountNo}
and sab.available_balance > 0
and (sab.account_type = 'BUYER' or (sab.account_type = 'SUPPLIER' and sab.account_status = 'SUSPEND_REFUND'))
and not exists (
select abrd.sub_account_no
from account_balance_refund_detail abrd
where 1 = 1
and abrd.deleted = 0
and abrd.sub_account_no = sab.sub_account_no
and exists(
select 1
from account_balance_refund abr
where abr.deleted = 0
and abr.approve_status in ('PROCESS', 'INIT')
and abr.refund_order_no = abrd.refund_order_no
)
<if test="refundOrderNo != null and refundOrderNo != ''.toString()">
and abrd.refund_order_no != #{refundOrderNo}
</if>
)
<if test="subAccountNo!=null and subAccountNo!=''.toString()">
and sab.sub_account_no = #{subAccountNo}
</if>
sub_account_balance:二级账户信息表
account_balance_refund_detail:账户退款申请详情表(从)
account_balance_refund:账户退款申请表(主)
上述案例脚本,场景是查询一级账户下可退款账户信息,但该账户信息不能存在退款申请在途中,所以需要过滤掉在途状态的数据
(1):第一层查询可退的二级账户信息,限制不存在 not exists() 在途状态中
(2):第二层查询退款申请详情信息,但是该信息需要和主表关联,主表状态限制在途状态,除了当前这条退款申请信息(主)
(3):最后的结果就是可退的二级账户信息,不存在于在途中的退款申请信息中,除当前主退款申请信息之外
(4):特别注意:每层 exists 或 not exists 子查询与主查询之间的关联关系
五、开发中,可以用 HashMap 的key不可重复的特点,模拟分布式锁的效果
1、可以定义局部变量 Map lockMap = new HashMap(); 判断指定的 key 和 value 是否存在,做不同的业务处理
2、例如循环中重复调用一个接口或方法,凡是满足指定条件的只调用一次,这个时候就可以向 lockMap 变量中写入 key 和 value 作为调用(锁)标识,后续数据条目中再有满足此条件的,在 lockMap 中已经存在调用标识了,所以就不需要再次调用了
以下是待实际验证和待总结的内容:
1、用户、角色、权限业务分析和总结【表关系】
@Transactional实现原理
待验证代码功能备份:
1、解决Spring循环依赖问题
spring:
#解决Spring循环依赖问题
main:
allow-circular-references: true
2、使用 docker-compose
Docker:
建议使用docker-compose
使用yml文件配置 方便简化很多
3、