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

给实体类增加属性无须给表增加字段,第1张

目录

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 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 selectListWithExtColumn(Wrapper wrapper) {
        List 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 list) {
        if (ListUtil.isEmpty(list)) {
            return;
        }
        if (!(list.get(0) instanceof CostBaseEntity)) {
            return;
        }

        String tableName = this.getTableName();
        Set rowIdSet = new HashSet<>();
        for (T entity : list) {
            rowIdSet.add(this.getId(entity));
        }
        Multimap 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 缺点

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

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/919948.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-16
下一篇 2022-05-16

发表评论

登录后才能评论

评论列表(0条)

保存