简化场景:
有数据库表结构为
CREATE TABLE `study_score` (
`id` varchar(36) NOT NULL,
`st_id` varchar(32) DEFAULT NULL COMMENT '学生id',
`st_name` varchar(32) DEFAULT NULL COMMENT '学生名称',
`st_subject_code` varchar(32) DEFAULT NULL COMMENT '课程代号',
`st_core` int(11) DEFAULT NULL COMMENT '课程分数',
`create_by` varchar(50) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建日期',
`update_by` varchar(50) DEFAULT NULL COMMENT '更新人',
`update_time` datetime DEFAULT NULL COMMENT '更新日期',
`sys_org_code` varchar(64) DEFAULT NULL COMMENT '所属部门',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
需求:归类统计每个学生的成绩并如下图展示
序号 | 姓名 | 语文 | 数学 | 英语 | 物理 | 化学 | 生物 | 政治 | 历史 | 地理 |
1 | ||||||||||
2 | ||||||||||
3 |
代码解决方案:
定义前端视图实体类VO
package org.jeecg.modules.study.vo;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.jeecgframework.poi.excel.annotation.Excel;
@Data
@EqualsAndHashCode(callSuper = false)
@ApiModel(value = "学生成绩VO对象", description = "学生成绩VO对象")
public class StudyScoreVO {
/**
* 学生id
*/
@ApiModelProperty(value = "学生id")
private String stId;
/**
* 学生名称
*/
@Excel(name = "学生名称", width = 15)
@ApiModelProperty(value = "学生名称")
private String stName;
/**
* 语文分数
*/
@ApiModelProperty(value = "语文分数")
private Integer Chinese;
/**
* 数学分数
*/
@ApiModelProperty(value = "数学分数")
private Integer mathematics;
/**
* 英语分数
*/
@ApiModelProperty(value = "英语分数")
private Integer english;
/**
* 物理分数
*/
@ApiModelProperty(value = "物理分数")
private Integer physics;
/**
* 化学分数
*/
@ApiModelProperty(value = "化学分数")
private Integer chemistry;
/**
* 生物分数
*/
@ApiModelProperty(value = "生物分数")
private Integer biology;
/**
* 政治分数
*/
@ApiModelProperty(value = "政治分数")
private Integer politics;
/**
* 历史分数
*/
@ApiModelProperty(value = "历史分数")
private Integer history;
/**
* 地理分数
*/
@ApiModelProperty(value = "地理分数")
private Integer geography;
}
定义枚举类
package org.jeecg.modules.study.constant;
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
@Getter
public enum SubjectEnum {
/**
* 语文
*/
CHINESE("chinese", "语文"),
/**
* 数学
*/
MATHEMATICS("mathematics", "数学"),
/**
* 英语
*/
ENGLISH("english", "英语"),
/**
* 物理
*/
PHYSICS("physics", "物理"),
/**
* 化学
*/
CHEMISTRY("chemistry", "化学"),
/**
* 生物
*/
BIOLOGY("biology", "生物"),
/**
* 政治
*/
POLITICS("politics", "政治"),
/**
* 历史
*/
HISTORY("history", "历史"),
/**
* 地理
*/
GEOGRAPHY("geography", "地理");
private final String code;
private final String name;
}
实现的方法:
package org.jeecg.modules.study.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.jeecg.modules.study.constant.SubjectEnum;
import org.jeecg.modules.study.entity.StudyScore;
import org.jeecg.modules.study.mapper.StudyScoreMapper;
import org.jeecg.modules.study.service.IStudyScoreService;
import org.jeecg.modules.study.vo.StudyScoreVO;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @Description: 学生分数表
* @Author: jeecg-boot
* @Date: 2021-12-04
* @Version: V1.0
*/
@Service
public class StudyScoreServiceImpl extends ServiceImpl<StudyScoreMapper, StudyScore> implements IStudyScoreService {
@Override
public List<StudyScoreVO> listStudyScoreVO() {
//从数据库中查数据
List<StudyScore> studyScoreList = list();
//组装数据 思路 定义一个MAP 里边装单个vo的信息 每遍历一个数据 就看Map里是否有对应的VO 有直接判断并赋值
Map<String,StudyScoreVO> sMap = new HashMap<>(16);
for (StudyScore studyScore : studyScoreList) {
//取学生VO 取不到则new一个并放到Map中
StudyScoreVO vo = sMap.get(studyScore.getStId());
if (vo == null){
vo = new StudyScoreVO();
vo.setStId(vo.getStId());
vo.setStName(vo.getStName());
sMap.put(vo.getStId(),vo);
}
//判断并对相应的vo字段进行设值
if (SubjectEnum.CHINESE.getCode().equals(studyScore.getStSubjectCode())){
vo.setChinese(studyScore.getStCore());
}else if (SubjectEnum.MATHEMATICS.getCode().equals(studyScore.getStSubjectCode())){
vo.setChinese(studyScore.getStCore());
}else if (SubjectEnum.ENGLISH.getCode().equals(studyScore.getStSubjectCode())){
vo.setChinese(studyScore.getStCore());
}else if (SubjectEnum.PHYSICS.getCode().equals(studyScore.getStSubjectCode())){
vo.setChinese(studyScore.getStCore());
}else if (SubjectEnum.CHEMISTRY.getCode().equals(studyScore.getStSubjectCode())){
vo.setChinese(studyScore.getStCore());
}else if (SubjectEnum.BIOLOGY.getCode().equals(studyScore.getStSubjectCode())){
vo.setChinese(studyScore.getStCore());
}else if (SubjectEnum.POLITICS.getCode().equals(studyScore.getStSubjectCode())){
vo.setChinese(studyScore.getStCore());
}else if (SubjectEnum.HISTORY.getCode().equals(studyScore.getStSubjectCode())){
vo.setChinese(studyScore.getStCore());
}else if (SubjectEnum.GEOGRAPHY.getCode().equals(studyScore.getStSubjectCode())){
vo.setChinese(studyScore.getStCore());
}
}
return new ArrayList<>(sMap.values());
}
}
正常来说这么实现就完事了,后续如果需要扩展的话 直接对if进行扩展即可
下面是不正常但好玩的写法
要解决这个问题主要有两步
第一步从数据库中获取数据
第二步对获取的数据进行组装
我们要改变的就是第二步,加入函数来使得代码更好玩
package org.jeecg.modules.study.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.jeecg.modules.study.constant.SubjectEnum;
import org.jeecg.modules.study.entity.StudyScore;
import org.jeecg.modules.study.mapper.StudyScoreMapper;
import org.jeecg.modules.study.service.IStudyScoreService;
import org.jeecg.modules.study.vo.StudyScoreVO;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;
/**
* @Description: 学生分数表
* @Author: jeecg-boot
* @Date: 2021-12-04
* @Version: V1.0
*/
@Service
public class StudyScoreServiceImpl extends ServiceImpl<StudyScoreMapper, StudyScore> implements IStudyScoreService {
//科目->对应的赋值关系
private final static Map<String, Function<StudyScoreVO, Consumer<Integer>>> RELATION_MAP;
static {
RELATION_MAP = new HashMap<>(9);
RELATION_MAP.put(SubjectEnum.CHINESE.getCode(),t -> t::setChinese);
RELATION_MAP.put(SubjectEnum.ENGLISH.getCode(),t -> t::setEnglish);
RELATION_MAP.put(SubjectEnum.MATHEMATICS.getCode(),t -> t::setMathematics);
RELATION_MAP.put(SubjectEnum.PHYSICS.getCode(),t -> t::setPhysics);
RELATION_MAP.put(SubjectEnum.CHEMISTRY.getCode(),t -> t::setChemistry);
RELATION_MAP.put(SubjectEnum.BIOLOGY.getCode(),t -> t::setBiology);
RELATION_MAP.put(SubjectEnum.POLITICS.getCode(),t -> t::setPhysics);
RELATION_MAP.put(SubjectEnum.HISTORY.getCode(),t -> t::setHistory);
RELATION_MAP.put(SubjectEnum.GEOGRAPHY.getCode(),t -> t::setGeography);
}
@Override
public List<StudyScoreVO> listStudyScoreVO() {
//从数据库中查数据
List<StudyScore> studyScoreList = list();
//组装数据 思路 定义一个MAP 里边装单个vo的信息 每遍历一个数据 就看Map里是否有对应的VO 有直接判断并赋值
Map<String,StudyScoreVO> sMap = new HashMap<>(16);
for (StudyScore studyScore : studyScoreList) {
//取学生VO 取不到则new一个并放到Map中
StudyScoreVO vo = sMap.computeIfAbsent(studyScore.getStId(), key -> {
StudyScoreVO temp = new StudyScoreVO();
temp.setStId(studyScore.getStId());
temp.setStName(studyScore.getStName());
return temp;
});
//判断并对相应的vo字段进行设值
RELATION_MAP.getOrDefault(studyScore.getStSubjectCode(),t -> num -> {}).apply(vo).accept(studyScore.getStCore());
}
return new ArrayList<>(sMap.values());
}
}
后续只需要维护RELATION_MAP的关系即可达到扩展的效果,这样写的好处在于把该关注的可变动部分放大了,相当于把大的流程框架定死,然后变更可变部分;