0
点赞
收藏
分享

微信扫一扫

JAVA后台开发中思考和注意的问题复盘--配置篇

最近连续一周多没有更新状态了,主要还是接近接近年底了,各种事情赶进度,需求,设计,开发,开会。。。,闲来就把这段时间开发实现的功能需要注意的点做一些归纳和总结,主要讲的是配置篇。

关于后台内部系统配置开发,其实也是属于业务开发的,业务开发离不开增删改查导入导出,本篇将归纳出一些原则上需要注意的内容和实现需要思考的点,希望自己以后开发的时候,能够多一点心,跳过这些坑,提高开发的效率。

原则上的问题

开发之前

需要反复看文档思考开发时相关联的内容,需要注意的点.最好能够列出整合出一些点,这个功能的实现,需要涉及到我们自己的系统提供接口,什么应用场景下,会需要这个接口,把所有的需要实现的接口整理出来以后,1可以适当的根据使用场景进一步整理,看能不能进一步减少一些不必要的接口实现,把两个接口整合在一起就可以了。

注意点:

  1. 系统内部的配置管理,需要先确定数据源,表结构,各个表之间的关联。

  2. 内部配置,需要展示和条件过滤时,需要外部的那些表的数据进行关联,这些最好在开发之前确定。

  3. 类、方法注释,一般是使用统一的公司内部规定,提前定义好,省的开发到一半,
    部门内部突然改了,很麻烦。注释方面,一般类都需要注释,一般使用java开发时,controller层、service层接口类、mapper接口必备,service、mapper实现类就不再注释了。

4.是否打印异常、业务日志
原则上,按照公司规定,不过配置方面的基本就是普通的增删改查,一般不需要,而且如果是自己内部使用,更加不需要了。

5.事务方面

读事务以及写事务。根据执行的读事务,如果是单表,基本不需要,如果是业务涉及到两张表及以上,建议添加备注。写事务根据具体条件。

  1. 代码规约提交方面

这方面的话,我是建议开发完一个模块(未提测),在代码逻辑方面设计没问题了,在提交之前每次都需要使用阿里代码插件,以及pmd(有的公司有要求,自己定义的规范)进行扫描。开发的时候,因为可能频繁的改动,每次都去修改这些的话,可能还是会花不少时间的。

7.确认跟前端交互需要的一些入参,出参(配置方面,我们都是前后台自己开发的,搭建vue,全栈,所以在文档下开发,一些细节可以在测试的时候,再更改),必要的字段必须展示。

  1. VO定义


这个也是根据公司部门要求来就好,只是需要先确认好,不然后期修改,维护,代码可读性方面会有影响。比如请求进来接收vo,需要专门定义一个接收VO,查询时,map中的数据,根据是否有其他字段不同,阿里规约是建议使用Do,数据库操作对象。

9.用户登录、数据权限控制!!

这块建议写一个公众类,必须,用户需要验证登录权限,才能查询对应的某些数据权限比如(城市、门店、车型举例自己公司的),类似拦截器,验证是否登录,将具备的权限提前构造进去。基本的配置操作,看业务要求,一般都需要这些数据,不建议每个接口都去判断一次。

10.分页(继承共用类,降低代码侵入性)!!

分页方面,我们的处理是继承一个pageVO,包含currentPage、pageSize等,编写一个拦截器,使用特定的查询命名,在查询时能够降低代码的侵入性,只需要查询的vo,具有currentPage、pageSize这两个属性就可以了。实现是在mybatis运行时,每个查询都会进行分页处理,嵌入修改sql。对普通开发者来说,只需要实现sql语句,查询全部就可以了。

原先,使用的是mybatis pagehelper,构建一个pageInfo的,这样的做法,虽然很快,但是每个人还是需要写构建一次分页,太麻烦了。

  1. // TODO : 待办事件补充

开发的时候,可能某些数据没有条件获取,又需要进行设置,加入数据库,或者测试时需要先走大概流程,可以加一个 // todo 注释, 后续比较方便找到需要修改的地方

增删改查导出入

新增、修改(与导入)

关于配置信息的新增、修改(两个根据需要是否考虑事务)以及导入,其实是可以整合成一个接口进行关联的,我说的是业务方法,根据是否存在主键id,判断执行新增或者更新业务。

新增时,考虑是否加事务,后台需要根据条件判断是否已存在该记录,因为是配置,基本都需要保证唯一性,如果已经存在,一般是返回已经存在,抛异常,不存在则新增(业务方面也可能要求,存在就更新进去)。

修改时,考虑是否加事务,执行修改,考虑修改如果涉及到多表的情况处理,同步更新。

导入时,与新增不同的是,基本都是使用excel格式,导入,分为单表导入,多表导入,大致的流程都是如下(我们系统的处理):

1.前端方面,我是使用vue+elementUI,前端方面,会有有一篇专门的更新,这里不做细说,需要运行提交文件:

this.$refs.upload.submit()  ,传入一个importBeanId: 'cityModelRadiusExcelServiceImpl'  
这个id是对应的业务层的springbeanid

2.后台会抽离出一些公用的excel验证方法(导出格式化,导入时数据验证,excel编码格式转化,导出数据组装,基础校验,获取cell信息等等),我们实现时会继承该方法,并重写导入导出方法,具体的字段验证需要自己实现。

3.导入导出会根据自己的需求去编写,一般需要进行非空等校验,其次需要判断是否存在对应的属性名,比如导入城市,门店,需要判断这些门店是否存在,等等信息,然后构建。

4.构建后,需要根据不同情况进行不同的操作:

这块建议使用开源的框架,公司的用的封装一般,一直被一个高级的开发吐槽的。

单表导入处理,excel数据方面需要验证哪些字段,导入的数据量过大,进行批量导入sql执行,数据过滤后,同样需要考虑,导入的数据重复的问题:

目前处理:
导入前,需要查询原表是否已存在该数据,我的唯一性判断涉及到两个条件,比如 城市id+门店id。看代码逻辑:

@Transactional(value = "mysqlTransactionManager", readOnly = false, rollbackFor = Throwable.class)
    public void insertOrUpdateSupplyVehicleTimeExcel(List<InvCityDeptConfigFormVo> cityDeptConfigList) {
        // 过滤已存在的重复的城市和门店id
        Set<Long> cityIds = cityDeptConfigList.stream().map(InvCityDeptConfigFormVo::getCityId).collect(Collectors.toSet());
        Set<Long> deptIds = cityDeptConfigList.stream().map(InvCityDeptConfigFormVo::getDeptId).collect(Collectors.toSet());

        User user = RequestUtil.getUser();
        List<InvCityDeptConfigFormVo> insertVos = new ArrayList<>();
        List<InvCityDeptConfigFormVo> updateVos = new ArrayList<>();
        InvCityDeptConfigFormVo cityDeptConfigFormVo = new InvCityDeptConfigFormVo();
        String cityIdsStr = cityIds.toString();
        String deptIdsStr = deptIds.toString();
        cityDeptConfigFormVo.setCityIds(cityIdsStr.substring(1,cityIdsStr.length()-1));
        cityDeptConfigFormVo.setDeptIds(deptIdsStr.substring(1,deptIdsStr.length()-1));
        // 执行查询
        List<String> reList = cityDeptConfigMapper.getCityDeptConfigStringList(cityDeptConfigFormVo);

        // 查询出的结果与重复的执行过滤
        cityDeptConfigList.forEach(vo -> {
            String s = vo.getCityId() + "_" + vo.getDeptId();
            if(reList.contains(s)){
                vo.setModifyEmp(Long.parseLong(user.getUserId()));
                vo.setModifyTime(new Date());
                updateVos.add(vo);
            } else {
                insertVos.add(vo);
            }
        });

        //  批量更新
        updateVos.forEach(vo->{
            cityDeptConfigMapper.updateInvCityDeptConfigVo(vo);
        });
        // 批量插入
        if(insertVos.size() > 0) {
            cityDeptConfigMapper.insertBatchCityDeptConfigVo(insertVos);
        }
        return ;
    }

查询重复的sql语句如下:

 select
        concat(city_id,'_',dept_id)
        FROM
        t_inv_city_dept ticd
        where 1 = 1
        <if test="null != cityIds and cityIds != ''">
            and ticd.city_id in (${cityIds})
        </if>
        <if test="null != deptIds and deptIds != ''">
            and ticd.dept_id in (${deptIds})
        </if>
        order by id

因为我是涉及到多个条件id的处理。

第二种实现:

l利用mysql语法中的批量执行插入,如果存在就执行更新。需要做的实现:
以上面的为例: 需要加城市和门店的索引。(因为涉及到业务id,按照sql规范是不能加所以的,也就是说 这条行不通,但是要加也可以的)

如果执行查询的是唯一的条件,比如其他主键,那么可以直接查询出来后,去重。

多表导入处理(一定要考虑事务回滚),这个意思是指,有些配置是包括普通配置主表和对应的配置详情表的,一条主表记录,可能需要一条甚至多条详情表,在进行excel数据字段进行条件判断过滤后,需要构建对应的数据结构,才能执行插入数据库。

举个例子:比如详情表是根据主表中的两个字段进行分辨的,可以构建一个vo对象,里面包含主表的信息,同时需要再构建一条甚至多条详情表的信息,设置字段为info,这里还需要考虑下是否需要根据某些字段排序,便于查询时展示,因为导入是需要一条记录同时导入成功,才算成功的,需要做写事务控制。

至于为什么不执行批量导入,是因为连接到多张表。

查询

单表配置表查询,单表查询的话,也可能需要关联其他表来获取对应展示字段信息的,本表是否有逻辑删除字段,是否有效status等等条件,在写sql条件时,需要确定好,思考下,是否需要构建索引,减少join的表数。

多表查询,跟单表差不多,后续有其他再更新。

查询方面,基本都要考虑是否需要数据权限控制。

其他的主要是sql方面的优化,如果有实际数据,可以自测下,能够进行优化的点。

删除

两块,逻辑删除(软删),或者物理删除,开发之前要确认好,这块也可能跟查询关联的。isdeleted字段。逻辑删除,建议命名deleted、del,物理删除为remove。。个人建议,软删就是命名删除,真正执行的是修改isDeleted字段操作。

增删改查考虑点:

1.事务
2.异常处理
3.尽量少些接口复用
4.分页优化,减少代码侵入性
5.权限优化
。。。。

有更好的解决方案,欢迎留言或评论,一起进步,促进。。。

待续更新

举报

相关推荐

0 条评论