自定义扩展字段设计与实现,产品思维的提升

自定义扩展字段设计与实现,产品思维的提升

(这部分内容是我工作中的一些工作成长总结,大家不喜欢可以直接进行跳过,跳转到自定义扩展字段实现)

在本周的工作,导师让我们实现自定义扩展业务。

周一: 分析扩展字段解决方案,实现扩展字段的用户需求,扩展字段所用到的技术, 由于导师请假,看不太懂导师所描述的技术方向,产品需求,就没有选择师傅的扩展字段解决方案。 在没有分析清楚产品需求的情况下,就进行了代码的编写,想采用反射等一类技术来实现动态字段扩展,没有考虑到用户在某个场景下,如何编辑的在扩展字段中添加数据。导致我解决的方案代码,不具有很大的价值

经过反思:编写业务前,一定要反复斟酌,技术为产品而生,编写业务的过程中要具有产品思维,这样做是不是合理的,这样做会不会给用户带来极大的便利,选择一个自己擅长的技术,可能不是完美产品的解决方案,选择产品最适合的技术,虽然不是很擅长,这不正是自己的一种提升吗?

第二天:导师:针对我的解决方案,和代码提出了很多场景下的问题,经过深思熟虑后给出了解决的问题的方式,但是我的解决方案,并不是那么的完美,没有考虑到性能的问题,最终采用Map数据结构来实现动态字段扩展。

第五天:自定义扩展业务已经全部实现,导师向我提出需要如何在搜索中能找到对应扩展字段对应的行数据。因为对es技术不熟悉,甚至有点懵的状态,当我看了公司的es业务后,分析这个庞大的问题,针对这个问题,我应该怎么一步一步去做。然后得到了一个一个细小的问题 ,针对这些问题向师傅提出问题,最终得到了解决问题的方式

当遇到一个问题的时候,找不到解决问题的方式,仔细梳理问题,应该思考如何把问题这个问题拆分成为一个一个小问题,当得到了一个一个细小的问题,就能得到最终问的解决方案。

自定义扩展字段实现

由于不在公司表结构设计不能给大家展示entity展示给大家

扩展字段存储表

vbnet 复制代码
public class ExtendEntity {


  private Long id;


  private Long accId;


  private Long objectId;

  private Long funcId;


  private String funcText;


  private String type;

  private LocalDateTime createdAt;

  private LocalDateTime updatedAt;



}

扩展字段表头

vbnet 复制代码
public class FunctionEntity {
    private Long id;
    private Integer functionType;

    private String functionMain;
    private String functionName;
    private Integer isnewfunc;
    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;

    // 省略构造函数和Getter/Setter方法
}

扩展字段开关表

vbnet 复制代码
public class FunctionSwitchEntity {
    private Long id;
    private Long accId;
    private Long functionId;
    private Integer orderNum;
    private Integer functionSwitch;
    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;
}

扩展字段表头开关 dao

java 复制代码
@Repository
public class FunctionSwitchDao {

    @Resource(name = SaasBusinessDsConfig.SaasBusinessDbJdbcTemplateName)
    private JdbcTemplate jdbcTemplate;

    @Resource(name = SaasBusinessDsConfig.SaasBusinessDbNamedParameterJdbcTemplateName)
    private NamedParameterJdbcTemplate namedParameterJdbcTemplate;

    public int PassupdateSwitch(long accId, long id, int functionSwitch) {
        StringBuilder ab = new StringBuilder();
        ab.append( "UPDATE t_function_switch SET functionswitch = :functionSwitch, updatedat = current_timestamp ");
        ab.append(   "WHERE accid = :accId AND id = :id");
        String sql = ab.toString();
        MapSqlParameterSource params = new MapSqlParameterSource();
        params.addValue("functionSwitch", functionSwitch);
        params.addValue("accId", accId);
        params.addValue("id", id);

        return namedParameterJdbcTemplate.update(sql, params);
    }

    public List<FunctionSwitchDto> getFunctionList(long accId, long funcType) {
        StringBuilder sb = new StringBuilder();
        sb.append( "SELECT fs.id, fs.functionid, f.functionname,f.functionmain,fs.orderNum,f.functiontype, fs.functionswitch, f.isnewfunc ");
        sb.append( "FROM t_function_switch fs " );
        sb.append("JOIN t_function f ON fs.functionid = f.id " );
        sb.append("WHERE fs.accid = :accId AND f.functiontype = :funcType ");
        sb.append("ORDER BY fs.orderNum;");
        MapSqlParameterSource params = new MapSqlParameterSource();
        params.addValue("accId", accId);
        params.addValue("funcType", funcType);

        String sql = sb.toString();

        RowMapper<FunctionSwitchDto> rowMapper = new BeanPropertyRowMapper<>(FunctionSwitchDto.class);

        List<FunctionSwitchDto> result = namedParameterJdbcTemplate.query(sql, params, rowMapper);
        if (result == null || result.isEmpty())
            return null;
        return result;
    }


    public void deleteAccid(long accId, long id) {
        String query = "DELETE FROM t_function_switch WHERE accid = :accId AND id = :id";

        Map<String, Object> parameters = new HashMap<>();
        parameters.put("accId", accId);
        parameters.put("id", id);

        namedParameterJdbcTemplate.update(query, parameters);
    }


    public int funcidCount(long funcId) {
        StringBuilder sb = new StringBuilder();
        sb.append( "SELECT COUNT(*) FROM t_function_switch WHERE functionid = :funcId");
        String query = sb.toString();
        SqlParameterSource parameters = new MapSqlParameterSource("funcId", funcId);
        return namedParameterJdbcTemplate.queryForObject(query, parameters, Integer.class);
    }


    public void insertSwitch(FunctionSwitchEntity functionSwitchEntity) {
        String query = "INSERT INTO t_function_switch (accid, functionid, functionswitch,ordernum, createdat, updatedat) " +
                "VALUES (:accId, :functionId, :functionSwitch, :ordernum ,  :createdAt, :updatedAt)";
        SqlParameterSource parameters = new MapSqlParameterSource()
                .addValue("accId", functionSwitchEntity.getAccId())
                .addValue("functionId", functionSwitchEntity.getFunctionId())
                .addValue("functionSwitch", functionSwitchEntity.getFunctionSwitch())
                .addValue("createdAt", functionSwitchEntity.getCreatedAt())
                .addValue("ordernum",functionSwitchEntity.getOrderNum() )
                .addValue("updatedAt", functionSwitchEntity.getUpdatedAt());
        namedParameterJdbcTemplate.update(query, parameters);


    }

扩展字段表头dao

ini 复制代码
@Repository
public class FunctionDao {

    @Resource(name = SaasBusinessDsConfig.SaasBusinessDbJdbcTemplateName)
    private JdbcTemplate jdbcTemplate;

    @Resource(name = SaasBusinessDsConfig.SaasBusinessDbNamedParameterJdbcTemplateName)
    private NamedParameterJdbcTemplate namedParameterJdbcTemplate;


    public void deleteById(long functionId) {
        String query = "DELETE FROM t_function WHERE id = :functionId";
        SqlParameterSource parameters = new MapSqlParameterSource("functionId", functionId);
        namedParameterJdbcTemplate.update(query, parameters);
    }

    public void insert(FunctionEntity functionEntity) {
        String query = "INSERT INTO t_function (id ,functiontype, functionmain, functionname, isnewfunc, createdat, updatedat) " +
                "VALUES (:id,:functionType, :functionMain, :functionName, :isNewFunc, :createdAt, :updatedAt)";

        Map<String, Object> parameters = new HashMap<>();
        parameters.put("id",functionEntity.getId() );
        parameters.put("functionType", functionEntity.getFunctionType());
        parameters.put("functionMain", functionEntity.getFunctionMain());
        parameters.put("functionName", functionEntity.getFunctionName());
        parameters.put("isNewFunc", functionEntity.getIsnewfunc());
        parameters.put("createdAt", functionEntity.getCreatedAt());
        parameters.put("updatedAt", functionEntity.getUpdatedAt());

        namedParameterJdbcTemplate.update(query, parameters);
    }


    public List<FunctionEntity> selectByType(long funcType) {
        String query = "SELECT * FROM t_function WHERE functiontype = :funcType";
        SqlParameterSource parameters = new MapSqlParameterSource("funcType", funcType);
        RowMapper<FunctionEntity> rowMapper = new BeanPropertyRowMapper<>(FunctionEntity.class);
        return namedParameterJdbcTemplate.query(query, parameters, rowMapper);
    }

    public FunctionEntity selectById(long id) {
        String query = "SELECT * FROM t_function WHERE id = :id";
        SqlParameterSource parameters = new MapSqlParameterSource("id", id);
        RowMapper<FunctionEntity> rowMapper = new BeanPropertyRowMapper<>(FunctionEntity.class);


        List<FunctionEntity> query1 = namedParameterJdbcTemplate.query(query, parameters, rowMapper);


        if (query1==null|| query1.isEmpty()){
             return null;
         }
         return query1.get(0);
    }


    public int updateHeaderName(FunctionEntity functionEntity) {
        String query = "UPDATE t_function SET functionname = :functionName ,updatedAt= :updatedAt  WHERE id = :id";
        Map<String, Object> parameters = new HashMap<>();
        parameters.put("functionName", functionEntity.getFunctionName());
        parameters.put("id", functionEntity.getId());
        parameters.put("updatedAt", functionEntity.getUpdatedAt());
        return namedParameterJdbcTemplate.update(query, parameters);
    }

}

使用HashMap 解决扩展字段业务实现

scss 复制代码
@Service
public class FunctionSwitchService {
    @Resource
    private FunctionSwitchDao functionSwitchDao;
    @Resource
    private FunctionDao functionDao;

    @Resource
    private ExtendDao extendDao;

    public List<FunctionSwitchDto> getFuncList(long accId, long funcType) {
        List<FunctionSwitchDto> functionList = functionSwitchDao.getFunctionList(accId, funcType);
        if ((functionList == null || functionList.isEmpty())) {
            int num = 0;
            List<FunctionEntity> functionEntities = functionDao.selectByType(funcType);
            for (FunctionEntity functionEntity : functionEntities) {
                FunctionSwitchReq functionSwitchReq = new FunctionSwitchReq();
                functionSwitchReq.setFunctionmain(functionEntity.getFunctionMain());
                functionSwitchReq.setFunctionname(functionEntity.getFunctionName());
                functionSwitchReq.setFunctionswitch(1);
                functionSwitchReq.setOrderNum(num);
                functionSwitchReq.setId(functionEntity.getId());
                insertSwitch(accId, (List<FunctionSwitchReq>) functionSwitchReq);
                num++;
            }
            functionList = functionSwitchDao.getFunctionList(accId, funcType);
        }
        return functionList;
    }

    //用户进行开关操作
    public List<FunctionSwitchDto> updateSwitch(long accId, long id, long funcType, int functionswitch) {
        functionSwitchDao.PassupdateSwitch(accId, id, functionswitch);

        List<FunctionSwitchDto> functionList = functionSwitchDao.getFunctionList(accId, funcType);
        return functionList;
    }


    public List<FunctionSwitchDto> insertSwitch(long accId, List<FunctionSwitchReq> functionSwitchReqs) {
        for (FunctionSwitchReq functionSwitchReq : functionSwitchReqs) {
            FunctionEntity functionEntity = new FunctionEntity();
            FunctionSwitchEntity functionSwitchEntity = new FunctionSwitchEntity();
            BeanUtils.copyProperties(functionSwitchReq, functionEntity);
            BeanUtils.copyProperties(functionSwitchReq, functionSwitchEntity);
            functionEntity.setFunctionMain(functionSwitchReq.getFunctionmain() == null ? functionSwitchReq.getFunctionname() : " ");
            functionEntity.setFunctionName(functionSwitchReq.getFunctionname());
            functionEntity.setCreatedAt(LocalDateTime.now());
            functionEntity.setId(functionSwitchReq.getId());
            functionEntity.setUpdatedAt(LocalDateTime.now());
            functionSwitchEntity.setId(null);
            functionSwitchEntity.setFunctionId(functionSwitchReq.getId());
            if (functionSwitchReq.getIsnew() != null && !functionSwitchReq.getIsnew().equals(0)) {
                functionEntity.setIsnewfunc(1);
                long l = UUIDUtils.generateUUID();
                functionSwitchEntity.setFunctionId(l);
                functionEntity.setFunctionType(functionSwitchReq.getFunctiontype());
                functionEntity.setId(l);
                functionDao.insert(functionEntity);
            }
            functionSwitchEntity.setOrderNum(functionSwitchReq.getOrderNum() == null ? 0 : functionSwitchReq.getOrderNum());
            functionSwitchEntity.setAccId(accId);
            functionSwitchEntity.setFunctionSwitch(functionSwitchReq.getFunctionswitch());

            functionSwitchEntity.setCreatedAt(LocalDateTime.now());
            functionSwitchEntity.setUpdatedAt(LocalDateTime.now());
            functionSwitchDao.insertSwitch(functionSwitchEntity);
        }

        return functionSwitchDao.getFunctionList(accId, functionSwitchReqs.get(0).getFunctiontype());
    }

    public void deleteSwitch(long accId, long id, long functionid) {
        FunctionEntity functionEntity = functionDao.selectById(functionid);
        if (functionEntity.getIsnewfunc() == 0) {
            new BussConstrainException("系统功能不能删除");
        }
        functionSwitchDao.deleteAccid(accId, id);
        if (functionSwitchDao.funcidCount(functionid) <= 0) {
            functionDao.deleteById(functionid);
        }
    }

    //也要根据状态进行查询,我根据列查询就不用使用
    public List<ExtendEntity> getFuncTableExtend(long accId, TableIdReq tableIdReq) {
        List<ExtendEntity> extendEntities = extendDao.getTableextend(accId, tableIdReq);
        return extendEntities;
    }

    public List<FunctionSwitchDto> updateTableHeader(long accId, TableHeaderReq tableHeaderReq) {
        FunctionEntity functionEntity = functionDao.selectById(tableHeaderReq.getFunctionid());
        if (functionEntity == null) {
            throw new BussConstrainException("id不存在");
        }
        if (functionEntity.getIsnewfunc().equals(0)) {
            throw new BussConstrainException("系统功能不能修改");
        }
        functionEntity.setUpdatedAt(LocalDateTime.now());
        functionEntity.setFunctionName(tableHeaderReq.getFunctionname());
        functionDao.updateHeaderName(functionEntity);
        return functionSwitchDao.getFunctionList(accId, tableHeaderReq.getFunctiontype());
    }

    public int addTableData(long accId, List<TableIdDataReq> tableIdReqs) {
        int i = 0;
        for (TableIdDataReq tableIdReq :
                tableIdReqs) {
            if (extendDao.getSelectTable(accId, tableIdReq) != null) {
                i += extendDao.updateTableData(accId, tableIdReq);
            } else {
                i += extendDao.addTableData(accId, tableIdReq);
            }
        }
        return i;
    }

    public int updateTableData(long accId, TableIdDataReq tableIdReq) {

        return extendDao.updateTableData(accId, tableIdReq);
    }

    /**
     * @param accId          商家id
     * @param userId         用户id
     * @param aggregateQuery 商家传递参数
     * @return
     */
    public Map<Long, Map<Long, ExtendEntity>> getDataColums(long accId, long userId, TableIdReq aggregateQuery) {
        List<FunctionSwitchDto> funcList = this.getFuncList(accId, aggregateQuery.getFuncType());

        List<FunctionSwitchDto> collect = funcList.stream()
                .filter(dto -> dto.getIsnewfunc() == 1)
                .collect(Collectors.toList());

        List<Long> functionIds = collect.stream()
                .map(FunctionSwitchDto::getFunctionid)
                .collect(Collectors.toList());
        //比如有三列  他查询出来的是三列的数据
        List<ExtendEntity> extendTable = getFuncTableExtend(accId, new TableIdReq(functionIds, aggregateQuery.getObjectId()));

        Map<Long, List<ExtendEntity>> extendMap = extendTable.stream().collect(Collectors.groupingBy(k -> k.getObjectId()));

        Map<Long, List<ExtendEntity>> resultMap =
                extendTable.stream()
                        .collect(Collectors.groupingBy(ExtendEntity::getFuncId));

        Map<Long, Map<Long, ExtendEntity>> newMap = resultMap.entrySet().stream()
                .collect(Collectors.toMap(
                        Map.Entry::getKey,
                        entry -> entry.getValue().stream()
                                .collect(Collectors.toMap(ExtendEntity::getObjectId, entity -> entity))
                ));
        return newMap;


    }


    public List<ExtendVo> getGoodsIdColumn(long accId, long goodsId) {
        return extendDao.getGoodsIdColomn(accId,goodsId );
    }
}

搜索引擎中添加扩展字段

当商品 进行存储的时候,远程调用拿到对应的行数据,将所有的map结构, 塞入到商品对应的行

上周工作总结:

同步数据库全自动化数据迁移 功能已全部完成 ,等待导师切换sqlserver 业务支持pgsql,同步任务。预计半个月后完成全部迁移任务。

编写同步数据业务,采用反射,流,算法思维,等技术,实现自动化导出数据库表功能,生成自定义数据库表格,自定义entity,大部分数据库都能正常导出数据,自动插入到新的数据库。

相关推荐
向前看-25 分钟前
验证码机制
前端·后端
超爱吃士力架2 小时前
邀请逻辑
java·linux·后端
AskHarries4 小时前
Spring Cloud OpenFeign快速入门demo
spring boot·后端
isolusion5 小时前
Springboot的创建方式
java·spring boot·后端
zjw_rp5 小时前
Spring-AOP
java·后端·spring·spring-aop
TodoCoder6 小时前
【编程思想】CopyOnWrite是如何解决高并发场景中的读写瓶颈?
java·后端·面试
凌虚7 小时前
Kubernetes APF(API 优先级和公平调度)简介
后端·程序员·kubernetes
机器之心7 小时前
图学习新突破:一个统一框架连接空域和频域
人工智能·后端
.生产的驴8 小时前
SpringBoot 对接第三方登录 手机号登录 手机号验证 微信小程序登录 结合Redis SaToken
java·spring boot·redis·后端·缓存·微信小程序·maven
顽疲8 小时前
springboot vue 会员收银系统 含源码 开发流程
vue.js·spring boot·后端