目录
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、问题背景
随着系统的运行,由于需求不断的迭代,业务不断的深入,会发现我们当属对一个实体进行表结构设计满足不了当前、未来的需求,经常需要加字段。从技术手段上说,加字段,涉及到以下步骤:
- 给实体类Entity增加新属性(预估耗时3分钟)
- 给实体类映射文件xml文件增加新字段与新属性的映射关系(预估耗时3分钟)
- 给VO类增加新属性(预估耗时3分钟)
- 将字段增加的sql脚本向运维登记,有些甚至需要在客户环境进行执行。(流程很长)
加字段第1、2、3步,虽然耗时不长,但是需要人参与,有人参与就极其容易出现错误,最重要的加字段要走sql变更流程,这个流程非常长,一次sql变更,要涉及运维,测试上线,流程繁琐,
特别是一些经常加字段的表,就显得问题更为突出。
那么除了给表新增加字段,有没有其他方法,可以解决这个问题。当然有,请继续阅读。
2、解决方案我们可以将列转行,将表的逻辑列转换为数据行。fk_fkdzb_ext表结构如下:
我们有业务表fk_fkdzb(付款单主表),例如我们要给fkdzb增加两个字段:扣留款金额,散货码头费,则需要在fk_fkdzb_ext表增加两条数据。
这个称之为“列转行”方案。
那么如何做到,让业务层实现无感知,让前端无须修改代码即可做到可以自定义字段的增加?
请仔细阅读下面代码示例:
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 缺点表的可读性要差一些,获取一个表的所有字段信息,需要进行连表查询,效率与性能上要差一些
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)