JAVA后台动态获取增删改的变化实体

背景

项目后台有一个修改告警规则的功能,对应的前端部分页面如下。

在这里插入图片描述
上面这个页面数据传到后台,对应的数据结构为:

一个AlarmRule里有多个AlarmTarget,一个AlarmTarget里有多个AlarmCondition。

在这里插入图片描述
上面这个页面数据传到后台,对应的数据结构为:

一个AlarmRule里有多个AlarmHandleFlow,一个AlarmHandleFlow里有多个AlarmHandleRule。

页面里其他地方也有类似的数据结构,此处就不全部展示了。目前导致的问题是:

由于界面涉及大量有父子关系的数据结构,当调用后台修改接口时,研发人员不好判断哪些数据是新增的、哪些是修改的、哪些是被删除的,导致目前修改接口的实现逻辑是先删除所有旧的数据,再新增新的数据。

这样做也不是不可行,只是有点“小题大作”:

如果我在页面只改了某一个元素,后台也要“大动干戈”地影响所有没有被修改的数据。

所以,需要引入一种优化方案,让后台不仅能动态获取增删改的变化实体,而且只修改有变化的实体数据。

数据结构设计

对于每种数据来说,都可能会涉及增、删、改,所以后台用泛型类ChangedEntityDTO表示

public class ChangedEntityDTO<T> {
    private List<T> updateList;
    private List<T> insertList;
    private List<T> deletedList;
}

其中updateList、insertList、deletedList集合类型的成员,分别表示修改、新增、删除的数据。

接口设计

1.获取ChangedEntityDTO的接口

定义ChangedEntityDTO结构之后,现在就需要考虑如何在后台获取ChangedEntityDTO类和其中的变化元素。

  • 首先,设计一个泛型接口来抽象父和子
public interface ChangedEntityService<PARENT, CHILDREN> {
    ChangedEntityDTO<CHILDREN> getChangedEntity(PARENT parent);
}

接口说明如下:

其中PARENT表示父,CHILDREN表示子。比如PARENT代表AlarmRule,CHILDREN代表AlarmTarget,以此类推。
getChangedEntity方法根据PARENT类型参数返回ChangedEntityDTO<CHILDREN>类型。

  • 然后,项目原先的业务层接口需要继承ChangedEntityService接口

以原先的AlarmTargetService接口为例,如下

public interface AlarmTargetService extends ChangedEntityService<AlarmRule, AlarmTarget>
  • 最后,实现其中的getChangedEntity方法

这是整个设计的核心逻辑,即需要知道哪些是新增的、哪些是修改的、哪些是删除的。还是以AlarmTargetService 为例子,具体代码如下

  @Override
    public ChangedEntityDTO<AlarmTarget> getChangedEntity(AlarmRule alarmRule) {
        AlarmTarget filter = new AlarmTarget();
        filter.setAlarmRuleId(alarmRule.getAlarmRuleId());
        List<AlarmTarget> oldList = alarmTargetDao.selectAlarmTargetList(filter);
        List<AlarmTarget> newList = alarmRule.getAlarmTargetList();

        //防止原引用修改
        List<AlarmTarget> needInsertList = new ArrayList<>(newList);
        List<AlarmTarget> needUpdateList = new ArrayList<>(newList);
        List<AlarmTarget> needDeletedList = new ArrayList<>(oldList);

        //获取数据库已存在的alarmTarget对象的主键alarmTargetId
        List<Integer> oldIds = oldList.stream().map(AlarmTarget::getAlarmTargetId).collect(Collectors.toList());
        //获取页面传过来的alarmTarget对象的主键alarmTargetId
        List<Integer> newIds = newList.stream().map(AlarmTarget::getAlarmTargetId).collect(Collectors.toList());

        //获取需要新增的对象
        needInsertList.removeIf(alarmTarget -> oldIds.stream().anyMatch(id->id.equals(alarmTarget.getAlarmTargetId())));
        log.info("需要新增的AlarmTarget对象={}", needInsertList);

        //获取需要删除的对象
        needDeletedList.removeIf(alarmTarget -> newIds.stream().anyMatch(id->id !=null && id.equals(alarmTarget.getAlarmTargetId())));
        log.info("需要删除的AlarmTarget对象={}", needDeletedList);

        //获取需要修改的对象
        needUpdateList = needUpdateList.stream().filter(alarmTarget -> oldIds.stream().anyMatch(id->id.equals(alarmTarget.getAlarmTargetId()))).collect(Collectors.toList());
        log.info("需要修改的AlarmTarget对象={}", needUpdateList);
        
		//构造ChangedEntityDTO
        ChangedEntityDTO<AlarmTarget> dto = new ChangedEntityDTO<>();
        dto.setDeletedList(needDeletedList);
        dto.setInsertList(needInsertList);
        dto.setUpdateList(needUpdateList);
        return dto;
    }

此时,我们就获得了ChangedEntityDTO<AlarmTarget>

2.处理ChangedEntityDTO的接口

通过上面的接口,我们已经获取到ChangedEntityDTO<AlarmTarget>和其中的变化元素了,现在就需要分别处理这里面的增删改实体,实现具体的业务逻辑。

  • 首先,设计包含增、删、改功能的接口
public interface ChangedEntityHandlerService<PARENT, ENTITY> {
    void handDeleted(List<ENTITY> entities);

    void handUpdate(PARENT parent, List<ENTITY> entities) throws Exception;

    void handInsert(PARENT parent, List<ENTITY> entities) throws Exception;
}

接口说明如下:

同前面接口一样,PARENT表示父,ENTITY表示子。三个方法的集合类型入参,分别对应 ChangedEntityDTO里的deletedListupdateList、insertList。

  • 然后,项目原先的业务层接口需要继承ChangedEntityHandlerService接口

比如,AlarmTargetService也继承ChangedEntityHandlerService接口

public interface AlarmTargetService extends ChangedEntityService<AlarmRule, AlarmTarget>, ChangedEntityHandlerService<AlarmRule, AlarmTarget> 
  • 最后,分别实现其中的增删改方法

比如,handDeleted会从数据库删除元素,handUpdate修改数据库元素,handInsert会往数据库插入元素。因为与具体业务相关,具体代码就不再展示。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值