Java处理数据库结果集返回JSON
后端开发时,面临各种各样的需求,那本文就以实际开发中的项目需求为依托,从描述项目需求开始到需求实现为止,记录这样一整个需求的开发过程经常和数据库打交道的过程
Java处理数据库结果集返回JSON
前言
后端开发时,面临各种各样的需求,那本文就以实际开发中的项目需求为依托,从描述项目需求开始到需求实现为止,记录这样一整个需求的开发过程经常和数据库打交道的过程,
一、项目需求是什么?
前端需要请求访问数据库中的数据,但是这个数据是有一定格式的,请编写后端接口,按照前端需要的格式把数据组织好。
二、分析步骤
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());
}
}
更多推荐
所有评论(0)