给实体类增加属性无须给表增加字段

目录

1、问题背景

2、解决方案

3、代码示例

3.1 实体类需要继承一个CostBaseEntity基类

3.2 保存实体类自定义字段

3.3 查询实体类自定义字段

3.4 columnNameAndColumnValueMap属性扁平化

3.4.1 如何接收前端自定义字段

3.4.2 如何向前端输出自定义字段

        3.5 对BaseServiceImpl进行装饰

4、总结

4.1 优点

4.2 缺点


1、问题背景

随着系统的运行,由于需求不断的迭代,业务不断的深入,会发现我们当属对一个实体进行表结构设计满足不了当前、未来的需求,经常需要加字段。从技术手段上说,加字段,涉及到以下步骤:

  1. 给实体类Entity增加新属性(预估耗时3分钟)
  2. 给实体类映射文件xml文件增加新字段与新属性的映射关系(预估耗时3分钟)
  3. 给VO类增加新属性(预估耗时3分钟)
  4. 将字段增加的sql脚本向运维登记,有些甚至需要在客户环境进行执行。(流程很长)

     加字段第1、2、3步,虽然耗时不长,但是需要人参与,有人参与就极其容易出现错误,最重要的加字段要走sql变更流程,这个流程非常长,一次sql变更,要涉及运维,测试上线,流程繁琐,
特别是一些经常加字段的表,就显得问题更为突出。

那么除了给表新增加字段,有没有其他方法,可以解决这个问题。当然有,请继续阅读。

2、解决方案

     我们可以将列转行,将表的逻辑列转换为数据行。fk_fkdzb_ext表结构如下:

通用表结构:

我们有业务表fk_fkdzb(付款单主表),例如我们要给fkdzb增加两个字段:扣留款金额,散货码头费,则需要在fk_fkdzb_ext表增加两条数据。

    这个称之为“列转行”方案。

      那么如何做到,让业务层实现无感知,让前端无须修改代码即可做到可以自定义字段的增加?
请仔细阅读下面代码示例。

3、代码示例

3.1 实体类需要继承一个CostBaseEntity基类

 

 

3.2 保存实体类自定义字段

3.3 查询实体类自定义字段

3.4 columnNameAndColumnValueMap属性扁平化

       需要在DTO对象上定义一个Map用来接收自定义字段,加@JsonAnySetter注解为了实现扁平化

    @JsonAnySetter
    private Map<String, String> columnNameAndColumnValueMap= new HashMap<>();

 实际上自定义字段与表中基本字段使用完全一样,前端是无感知的,完全兼容。

3.4.1 如何接收前端自定义字段

{
    "id": "1525DEB4EDCBD001",
    "fkdzbId": "1525DEB4CB4BD003",
    "enterpriseId": "TeddyPandaX",
    "attrKey": "automobileTransportationFee",
    "attrName": "汽运零担费",
    "attrValue": "30",
    " createdTime": "2022-05-10 11:33:57",
    //新增加字段 dockFee
    "dockFee": "20",
    //新增加字段 cashDiscountInterest
    "cashDiscountInterest": "0"
}

3.4.2 如何向前端输出自定义字段

{
    "id": "1525DEB4EDCBD001",
    "fkdzbId": "1525DEB4CB4BD003",
    "enterpriseId": "TeddyPandaX",
    "attrKey": "automobileTransportationFee",
    "attrName": "汽运零担费",
    "attrValue": "30",
    " createdTime": "2022-05-10 11:33:57",
    //新增加字段 dockFee
    "dockFee": "20",
    //新增加字段 cashDiscountInterest
    "cashDiscountInterest": "0"
}

3.5 对BaseServiceImpl进行装饰

     对底层的insert()方法进行装饰重写,如果实体类继承自CostBaseEntity并且自定义字段map不为空,则需要保存自定义属于到表fk_fkd_ext_column表。

 新增加一个方法selectListWithExtColumn(),可以完成查询实体列表并加载其自定义字段信息

  protected List<T> selectListWithExtColumn(Wrapper<T> wrapper) {
        List<T> list = super.selectList(wrapper);
        this.setExtColumns(list);
        return list;
    }

 /**
     * 
     * 给list设置自定义字段
     * @author LiQiao
     * @date 2022年5月10日 下午4:01:25
     * @param list
     */
    private void setExtColumns(List<T> list) {
        if (ListUtil.isEmpty(list)) {
            return;
        }
        if (!(list.get(0) instanceof CostBaseEntity)) {
            return;
        }

        String tableName = this.getTableName();
        Set<String> rowIdSet = new HashSet<>();
        for (T entity : list) {
            rowIdSet.add(this.getId(entity));
        }
        Multimap<String, FkFkdExtColumnDTO> rowIdAndFkFkdExtColumnDTOListMap =
            this.fkFkdExtColumnService.listColumnMetadata(tableName, rowIdSet);
        for (T entity : list) {
            String rowId = getId(entity);
            this.setExtColumns(entity, rowIdAndFkFkdExtColumnDTOListMap.get(rowId));
        }

    }

4、总结

     该方案实际上也是有优点,有缺点的,没有一个完美的方案,该方案解决了一些问题,同时也引起了另一些问题。

4.1 优点

     当需要给表加字段时无须对修改表结构了,无须走sql变更流程

4.2 缺点

    表的可读性要差一些,获取一个表的所有字段信息,需要进行连表查询,效率与性能上要差一些

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李桥s2008100262

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值