前言

    后端开发时,面临各种各样的需求,那本文就以实际开发中的项目需求为依托,从描述项目需求开始到需求实现为止,记录这样一整个需求的开发过程经常和数据库打交道的过程,


一、项目需求是什么?

    前端需要请求访问数据库中的数据,但是这个数据是有一定格式的,请编写后端接口,按照前端需要的格式把数据组织好。

二、分析步骤

1.分析

    首先熟悉项目架构,项目架构是springboot的架构,集成了很多工具,那本博客不全部列出,只列出与博客中提到的需求相关的技术栈,那本需求集成了swagger做接口处理,集成了jdbc(JdbcTemplate,NamedParameterJdbcTemplate)做数据库访问,集成了springMVC做架构处理,然后用到许多集合框架的思想。

2.误区1:误把dto当成mvc的组件之一

    最开始熟悉项目架构的时候,入手点在controller→service→dao→dto(entity),可实际上架构不是这么看的,mvc的架构就是在controller→service→dao,其中controller层定义好入参的校验,出参的返回类型;然后service层是进行数据处理,比如像数据筛选过滤;然后DAO层就是和数据库直接打交道,在DAO层编写sql语句,拿到需要处理的数据并返回给service处理。

3.误区2:误把数据获取和数据处理混为一谈

    实际上这个在项目中会分的比较清楚,就是我在DAO层只进行数据的获取,一次性做完数据的查询,然后再在service层拿到这些数据,这样把压力交给java端,减轻与数据库的交互,提升项目性能(每次和数据库交互完以后,拿到的数据会暂时放在硬盘中,从硬盘中拿数据和从内存中拿数据是完全不同的性能消耗,从硬盘中拿数据太慢了)

4.误区3:数据处理方面的思路不够开阔

    需求中需要的数据结果是两层,然后涉及到三张表,一张主表,一张从表,还有一张关联表,这三张表中没有关系依赖。但是逻辑清楚,通过sql语句去组织他们之间的关系。他们的表结构如下

-- 主表
CREATE TABLE `edp_sys_label_type` (
  `id` varchar(32) NOT NULL COMMENT '主键',
  `type_name` varchar(200) NOT NULL COMMENT '分类名称',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='企发发标签分类表'
-- 从表
CREATE TABLE `edp_label_info` (
  `label_id` varchar(32) NOT NULL COMMENT '标签id',
  `label_name` varchar(32) NOT NULL COMMENT '标签名称',
  `create_time` datetime NOT NULL COMMENT '标签创建时间',
  `label_type_id` int(11) NOT NULL COMMENT '标签类型id(0为数值,1为单选,2为多选)',
  `status` int(11) NOT NULL COMMENT '标签状态'
) ENGINE=InnoDB DEFAULT CHARSET=utf8
-- 关联表
CREATE TABLE `edp_sys_label_type_link` (
  `type_id` varchar(32) NOT NULL COMMENT '分类id',
  `label_id` varchar(255) NOT NULL COMMENT '标签id 一个分类id可以对应多个标签id'
) ENGINE=InnoDB DEFAULT CHARSET=utf8

所需出参格式:

{
  "status": 0,
  "msg": "操作成功",
  "data": [
    {
      "id": "10001",
      "typeName": "个人属性",
      "labelinfolist": [
        {
          "labelId": "1001",
          "labelName": "年龄",
          "createTime": "2022-06-29 15:02:34",
          "labelTypeId": 0,
          "status": 1
        },
        {
          "labelId": "1002",
          "labelName": "性别",
          "createTime": "2022-06-29 15:02:34",
          "labelTypeId": 1,
          "status": 1
        }
      ]
    },
    {
      "id": "10002",
      "typeName": "身份信息",
      "labelinfolist": [
        {
          "labelId": "1003",
          "labelName": "婚姻状况",
          "createTime": "2022-06-29 15:02:34",
          "labelTypeId": 1,
          "status": 1
        },
        {
          "labelId": "1004",
          "labelName": "教育程度编码",
          "createTime": "2022-06-29 15:02:34",
          "labelTypeId": 1,
          "status": 1
        }
      ]
    },
    {
      "id": "10003",
      "typeName": "终端情况",
      "labelinfolist": [
        {
          "labelId": "1005",
          "labelName": "终端品牌",
          "createTime": "2022-06-29 15:02:34",
          "labelTypeId": 2,
          "status": 1
        }
      ]
    },
    {
      "id": "10004",
      "typeName": "消费通信行为",
      "labelinfolist": [
        {
          "labelId": "1006",
          "labelName": "arpu",
          "createTime": "2022-06-29 15:02:34",
          "labelTypeId": 0,
          "status": 1
        }
      ]
    }
  ]
}

组装如上格式的出参,
1.直观但是麻烦的思路如下:最初的思路就是写两个sql,理由就是:我需要在遍历完主表以后去遍历从表,这样筛选有一个判断条件。两个for循环
①获取主表的所有数据

-- firstsql
select * from edp_sys_label_type;

②获取从表的所有数据同时连接到主表的id

-- secondsql
ELECT et.id,ei.label_id,ei.label_name,ei.create_time,ei.label_type_id,ei.`status` from edp_sys_label_type_link AS el 
LEFT JOIN edp_label_info  AS ei ON  el.label_id=ei.label_id 
LEFT JOIN edp_sys_label_type AS et ON et.id=el.type_id;

然后根据两个结果集中分类id是否相等来创建合适的对象,进而在service中组织想要的数据返回给controller

2.改进后的直观且方便的思路:也是写两个sql,但是不用判断,只有一层for循环
①获取主表的所有数据

-- firstsql
select * from edp_sys_label_type;

②有条件的获取从表的所有数据

-- secondsql
select * from edp_label_info a left join edp_sys_label_type_link b on a.label_id = b.label_id where b.type_id=

3.继续改进的方案是使用mybatis来做结果集查询,但是筛选思路和方案2一样


总结

以上就是今天要讲的内容,烦请大家多多指教出其中的缺点!万分感谢!


附上方案②的代码:
dto

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class GgDto {
    private String id;
    private String typeName;
    private List<OneGgDto> labelinfolist;
}
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class OneGgDto {
    private String labelId;
    private String labelName;
    private Date createTime;
    private int  labelTypeId;
    private int status;
}

DAO层:

import com.asiainfo.edp.base.model.dto.campmanage.GgDto;
import com.asiainfo.edp.base.model.dto.campmanage.OneGgDto;
import java.util.List;
public interface GgDao {
    List<GgDto> queryTestParentLabelInfo();

    List<OneGgDto> queryTestChildLabelInfo(String id);
}
import com.asiainfo.edp.admin.dao.GgDao;
import com.asiainfo.edp.base.model.dto.campmanage.GgDto;
import com.asiainfo.edp.base.model.dto.campmanage.OneGgDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Repository;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class GgDaoImpl implements GgDao {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Autowired
    private NamedParameterJdbcTemplate namedParameterJdbcTemplate;

    //持久化父标签信息
    @Override
    public List<GgDto> queryTestParentLabelInfo() {
        String parentsql="SELECT * FROM edp_sys_label_type ";

        List<GgDto> parentLabel = new ArrayList<>();
        //把执行sql获取到的结果集转换成bean对象,表中的字段和实体字段相对应
        parentLabel=jdbcTemplate.query(parentsql, new BeanPropertyRowMapper<>(GgDto.class));
        System.out.println("1111");
        System.out.println(parentLabel);
        System.out.println("2222");
        return parentLabel;
    }

    //持久化子标签信息
    @Override
    public List<OneGgDto> queryTestChildLabelInfo(String id){
        //String childsql="select * from edp_label_info a left join edp_sys_label_type_link b on a.label_id = b.label_id where b.type_id=:id ";
        String childsql="select * from edp_label_info a left join edp_sys_label_type_link b on a.label_id = b.label_id where b.type_id=:pageId ";
        Map<String, Object> map = new HashMap<>();
        map.put("pageId",id);
        List<OneGgDto> childLabel = new ArrayList<>();
        childLabel=namedParameterJdbcTemplate.query(childsql, map,new BeanPropertyRowMapper<>(OneGgDto.class));
        return childLabel;
    }
}

service层:

import com.asiainfo.edp.base.model.dto.campmanage.GgDto;
import com.asiainfo.edp.common.core.model.R;
import java.util.List;
public interface GgService {
    List<GgDto> getTestPageAllLabel();
}
import com.asiainfo.edp.admin.dao.GgDao;
import com.asiainfo.edp.admin.service.GgService;
import com.asiainfo.edp.base.model.dto.campmanage.GgDto;
import com.asiainfo.edp.base.model.dto.campmanage.OneGgDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import java.util.ArrayList;
import java.util.List;
@Slf4j
@Service
public class GgServiceImpl implements GgService {

    @Autowired
    private GgDao ggDao;
    @Override
    public List<GgDto> getTestPageAllLabel() {
        List<GgDto> endlist=new ArrayList<>();
        //接收父标签
        List<GgDto> parentlist = ggDao.queryTestParentLabelInfo();
        for(GgDto s:parentlist){
            //接收子标签
            List<OneGgDto> onelist= ggDao.queryTestChildLabelInfo(s.getId());
            s.setLabelinfolist(onelist);
            endlist.add(s);
        }
        return endlist;
    }
}

Controller:

import com.asiainfo.edp.admin.service.GgService;
import com.asiainfo.edp.base.model.dto.campmanage.GgDto;
import com.asiainfo.edp.common.core.annotation.NoLogin;
import com.asiainfo.edp.common.core.model.R;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
@Slf4j
@Api(tags = "测试")
@RestController
@RequestMapping("/ggController")
public class GgController {
    @Resource
    private GgService ggService;
    @ApiOperation("测试获取当前页面所有标签")
    @PostMapping("/getTestPageAllLabel")
    @NoLogin
    public R<List<GgDto>> getTestPageAllLabel(){
        return R.ok(ggService.getTestPageAllLabel());
    }
}

更多推荐