【业务功能篇20】Springboot java逻辑实现动态行转列需求

这篇具有很好参考价值的文章主要介绍了【业务功能篇20】Springboot java逻辑实现动态行转列需求。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

在此前,我也写过一个行转列的文章,是用存储过程sql处理的一个动态的逻辑

Mysql 存储过程\Mybatis框架call调用 实现动态行转列

那么后面我们同样又接收了业务的一个新需求,针对的是不同的业务数据,做的同样的一个展示数据报表,同样还是产品归属信息表头,拼接查询年月表头列,动态展示多个查询年月的产品产量数据。

  • 这里我们具体分析下业务需求:
  • 首先是一个业务产量表,记录着每个产品编码的产量数,产量时间
  • 另外是一个编码归属表,记录着每个产品编码的归属信息,属于哪个产品,哪个项目等的归属信息 

一般情况下,我们先设计后台表,然后先进行数据的sql处理,那么我们这里就从dao层开始来展开:

参数就是基于前台请求的参数类来传递,比如前端传递查询对象: 开始时间:2022-06,结束时间:2023-06,  只有时间,或者说还带上了一些 产品:产品A等

参数类:

package xxx.vo;

import java.util.List;


@Data
public class ProductionShipmentVO implements Serializable {

	private static final long serialVersionUID = 952332486490268095L;

	private String label;
	private String value;
	private List<String> proList;
	private List<String> itemList;
	private List<String> codeList;
	private List<String> taskNoList;
	private List<String> customerList;
	private List<String> contractList;
	private List<String> subList;
	private String isFlag;
	private String startTime;
	private String endTime;
	private String code;
	private Integer num;
	private String date;
	
	private String product;									//产品名
	private String project;                                 //项目
	private String jobNum;                                 //任务令号
	private String planStarttime;                          //计划开工时间 plan_starttime
	private String planEndtime;                            //计划完工时间 plan_endtime
	private String releaseTime;                            //释放时间 release_time
	private String jobStatus;                              //任务令状态 job_status
	private String itemcode;                                //编码 
	private String transactionQuantity;                    //交易数量 transaction_quantity
	private String transactionTime;                        //交易时间 transaction_time
	private String transactionDate;                        //交易日期 transaction_date
	private String transactionType;                        //交易类型 transaction_type
	private String groupId;                                //组织ID group_id
	private String subinventory;                            //子库
	private String supplierName;                           //供应商名称 supplier_name
	private String itemcodeCout;                           //单板点数 itemcode_cout
	private String processingLocationcode;                 //加工地代码 processing_locationcode
	private String processingLocationname;                 //加工地名称 processing_locationname
	private String productFamily;                          //产品族 product_family
	private String productSmall;                           //产品小类 product_small
	private String productBig;                             //产品大类 product_big
	private String smtLine;                                //SMT线体 smt_line
	private String itemcodeLine;                           //模块线体 itemcode_line
	private String system;                                  //系统源
	private String lastUpdatetime;                         //最后更新时间 last_updatetime
	private String lv1;                                     //l1部门
	private String lv2;                                     //l2部门
	private String lv3;                                     //l3部门
	private String lv4;                                     //l4部门
	private String type;                                    //类型
	private String locator;                                 //货位
	

}

dao层 mapper接口 

public interface IProductionShipmentDao {
    public List<ProductionShipmentVO> getYieldTabelProduct(ProductionShipmentVO productionShipmentVO);
}

dao层 xml文件映射

1. <sql id="yieldTabel"> 标签语句

我们把产量明细表 左联 编码归属表 的结果语句sql抽象出来放到一个sql标签中,作为共用调用的作用,可以结合业务场景判断,如果这个基础连表查询后续会多个地方需要调用,那么代码sql就可以抽出来一个sql标签中,避免重复代码过多

2.<sql id="listWhere"> 标签语句

同理与第一点,目前还是抽象出公共的语句,避免多处的接口sql重复代码过多,这里是一个参数的请求条件,也是极具通用的 多处地方可能会用到,所以就单独定义一个sql标签进行调用

3.<select id="getYieldTabelProduct" resultType="com.xxx.vo.ProductionShipmentVO">

调用标签1 作为临时表,然后根据产品 时间分组,对产量数求和,先得到一个表,每天数据表示: 产品A |  年月|  产量    的一个结果表,当然这里还需要将我们的年月的具体时间给转成列,并且对于的字段内容就是对应产品对应年月的产量。这个操作我们在service层再进行处理

	<sql id="yieldTabel">
		select A.*,IFNULL(B.PRODUCT_SERIES,'') PRODUCT_SERIES,IFNULL(B.MODEL,'') MODEL, IFNULL(B.MASS_DATE,'2500-01-01') MASS_DATE from txny.dwr_quality_xxx_proces_f A
		left join txny.dwr_mt_xxx_report_attr_f B on A.ITEM_CODE = B.PRODUCT_CODE where substr(A.JOB_NUM,3,1)='Z'  
	</sql>
	
	<sql id="listWhere">
		<where>
			<if test='isFlag == "1"'>
				and date_format(TIME_PERIOD,'%Y-%m-%d') > MASS_DATE 	
			</if>
			<if test='isFlag == "0"'>
				and date_format(TIME_PERIOD,'%Y-%m-%d')  <![CDATA[ <= ]]>  MASS_DATE 	
			</if>
			<if test="startTime != null and endTime != null">
				and date_format(TIME_PERIOD,'%Y-%m-%d') between #{startTime} and #{endTime} 	
			</if>
			<if test="proList != null and proList.size > 0">
				and PRODUCT_SERIES in 
				<foreach collection='proList' item="item" open="(" separator="," close=")">
					#{item}
				</foreach>
			</if>
			<if test="itemList != null and itemList.size > 0">
				and MODEL in 
				<foreach collection='itemList' item="item" open="(" separator="," close=")">
					#{item}
				</foreach>
			</if>
			<if test="codeList != null and codeList.size > 0">
				and ITEM_CODE in 
				<foreach collection='codeList' item="item" open="(" separator="," close=")">
					#{item}
				</foreach>
			</if>
		</where>
	</sql>
	
	<select id="getYieldTabelProduct" resultType="com.xxx.vo.ProductionShipmentVO">
		with table1 as (
			<include refid="yieldTabel"/>
		)
		select sum(QUANTITY) num,PRODUCT_SERIES product,date_format(TIME_PERIOD,'%Y-%m') date from  table1 
		<include refid="listWhere"/>
		group by PRODUCT_SERIES,date_format(TIME_PERIOD,'%Y-%m') order by PRODUCT_SERIES,date_format(TIME_PERIOD,'%Y-%m')
	</select>
	

 service层 impl实现类

通过运用java8新特性的 stream流处理数据转换,将dao层的接口方法返回的结果表:产品A |  年月|  产量   转换成一个 List<Map<String,Object>>集合,集合中每个元素Map就是一条横线的数据,比如:产品有多少个,list就有多少个元素,查询时间有多少个月,分别就会展示每个月该产品的产量以及合计产量

从而完成了数据年月的行转列

【业务功能篇20】Springboot java逻辑实现动态行转列需求

	@Named
public class ProductionShipmentService implements IProductionShipmentService {
	
	@Inject
	private IProductionShipmentDao iProductionShipmentDao;
	
	@Override
	public List<Map<String, Object>> getYieldTabelProduct(ProductionShipmentVO productionShipmentVO) {

        //取出前端传参的日期 格式为 yyyy-mm-dd 取出 起始年 月  截止年 月
		String[] sArr = productionShipmentVO.getStartTime().split("-");
		String[] eArr = productionShipmentVO.getEndTime().split("-");
		Integer sYear = Integer.valueOf(sArr[0]);
		Integer eYear = Integer.valueOf(eArr[0]);
		Integer sMonth = Integer.valueOf(sArr[1]);
		Integer eMonth = Integer.valueOf(eArr[1]);
		final List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
		List<ProductionShipmentVO> totaList = iProductionShipmentDao.getYieldTabelProduct(productionShipmentVO);
		totaList.stream().collect(Collectors.groupingBy(ProductionShipmentVO::getProduct,Collectors.collectingAndThen(Collectors.toList(), m ->{
			Map<String, Object> map = new HashMap<String,Object>();
            //遍历从起始到截止的查询年月 转换出区间内的每个年月 比如是23年6-9月 那么
            //date 就是表示 2023-06  2023-07 2023-08 2023-09 四个日期
			for (int i = sYear; i <= eYear; i++) {
				for (int j = 1; j <= 12; j++) {
					if((i== eYear && j> eMonth) || (i== sYear && j < sMonth)){
						continue;
					}
					String date =  String.valueOf(i)+"-"+(j < 10 ? "0"+String.valueOf(j): String.valueOf(j));

//anyMatch 有一个或一个以上的元素满足函数参数计算结果为true那整个方法返回值为true
//判断组内的数据中是否有该日期的数据 有则将其一条数据取出 
					if(m.stream().anyMatch(f->f.getDate().equals(date))){
						ProductionShipmentVO res = m.stream().filter(f->f.getDate().equals(date)).findFirst().get();

                        //map中插入日期 对应的产量  以及产品名称
						map.put(res.getDate(), res.getNum());
						map.put("product", res.getProduct());
					}else {
                        //如果没有该日期数据 就插入产量null
						map.put(date, null);
					}
				}
			}
            
            //每个年月数据取好之后,最后就是插入总累计产量
			Integer sum =  m.stream().mapToInt(ProductionShipmentVO::getNum).sum();
			map.put("num", sum);

            //把该产品的一条记录map插入list集合  依次将不同产品的map遍历插入
			result.add(map);
			return null;
		})));
		
		return result;
	}
}

那么前端框架,通过获取得到返回的数据,根据list中的元素map的键值对数,就能判断表头需要动态加载几列,比如前面展示的 查询3-6个月的数据那么表头展示就是这样:动态赋值获取表列数

【业务功能篇20】Springboot java逻辑实现动态行转列需求文章来源地址https://www.toymoban.com/news/detail-483656.html

到了这里,关于【业务功能篇20】Springboot java逻辑实现动态行转列需求的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java实现智慧社区业务综合平台 JAVA+Vue+SpringBoot+MySQL

    基于JAVA+Vue+SpringBoot+MySQL的智慧社区业务综合平台,包含了业务类型模块、基本业务模块、预约业务模块、业务分析模块、工作反馈模块和社区新闻模块,还包含系统自带的用户管理、部门管理、角色管理、菜单管理、日志管理、数据字典管理、文件管理、图表展示等基础模块

    2024年02月22日
    浏览(48)
  • 【业务功能篇104】 补充【业务功能篇99】微服务-springcloud-springboot-电商订单模块--整合支付

    在前面我们业务功能篇98-99中,我们介绍了电商项目中的订单模块服务,那么最后就是需要进行支付动作,那么我们这里就通过订阅第三方平台支付宝的支付调用接口功能,来进一步完成订单提交后的支付动作,支付宝的接口使用可以登录官网开发指南详情去了解 在我们对应

    2024年02月09日
    浏览(50)
  • 【业务功能篇53】Springboot 数据封装对象

    1) Entity:实体 ,与数据库的每一行数据打交道的,它的属性对应数据库每个字段 对应数据库的id,name,birthday等等字段,在CRUD中都会频繁用到 2) VO(View Object):视图类对象 ,属性对应前端页面用到的变量,例如用户登录页面涉及账号和密码,通过VO的封装传到HTML页面 3)

    2024年02月15日
    浏览(40)
  • Springboot项目怎么设计业务操作日志功能?

      很久以前都想写这篇文章,一直没有空,但直到现在我对当时的情景还有印象,之所以有印象是因为需求很简单,业务操作日志的记录与查询的功能,但是具体实现真的很烂,具体的烂法会在反面示例里细说,领导以及客户层面很认可,一系列迷之操作,让我印象深刻。

    2023年04月16日
    浏览(71)
  • 【业务功能115】微服务-springcloud-springboot-Kubernetes-k8s集群-Kubesphere实现DevOps流水线-CI/CD-SonarQube- Jenkins

    dev 怎么开发 ops 怎么运维 参考项目链接:https://github.com/kubesphere/devops-maven-sample 持续集成是指软件个人的部分向软件整体部分交付,频繁进行集成以便更快地发现其中错误。 CI需要具备这些: 全面的自动化测试 这是实践持续集成持续部署的基础,同时,选择合适的自动化测

    2024年02月04日
    浏览(89)
  • 【业务功能篇76】微服务网关路由predicates断言条件-filters路由转换地址-跨域问题-多级目录树化层级设计-mybatisPlus逻辑删除

    启动renren-fast如果出现如下错误 -Djps.track.ap.dependencies=false 添加相关配置即可 1.后端分类接口 JDK8特性:https://blog.csdn.net/qq_38526573/category_11113126.html 在后端服务中我们需要查询出所有的三级分类信息,并将这些信息组合为有父子关系的数据,所以首先我们需要在对应的entity中添

    2024年02月11日
    浏览(53)
  • python + pytorch 多线程实现级联模型的业务逻辑

    如果 目标跟踪 的模型想要和图片分类的业务逻辑进行混合,该怎么实现? 下面,我们来看一个,基于YOLOv8 目标跟踪和 pytorch 图片分类,实现模糊场景下融合 一个简单的消息队列,进行逻辑判断的级联模型推理。

    2024年02月11日
    浏览(39)
  • SpringBoot自定义starter开发:IP计数业务功能开发

    🙈作者简介:练习时长两年半的Java up主 🙉个人主页:程序员老茶 🙊 ps:点赞👍是免费的,却可以让写博客的作者开心好久好久😎 📚系列专栏:Java全栈,计算机系列(火速更新中) 💭 格言:种一棵树最好的时间是十年前,其次是现在 🏡动动小手,点个关注不迷路,感

    2024年04月16日
    浏览(36)
  • 【业务功能篇57】Springboot + Spring Security 权限管理 【上篇】

    4.1.1 权限管理的意义 后台管理系统中,通常需要控制不同的登录用户可以操作的内容。权限管理用于管理系统资源,分配用户菜单、资源权限,以及验证用户是否有访问资源权限。 4.1.2 RBAC权限设计模型 ACL介绍 ACL(Access Control List):访问控制列表 用户 - 权限 ACL 模型,权限

    2024年02月15日
    浏览(42)
  • springboot业务功能实战(四)告别轮询,websocket的集成使用

    org.springframework.boot spring-boot-starter-websocket 加入配置类 @Configuration public class WebSocketConfig { /** 注入ServerEndpointExporter, 这个bean会自动注册使用了@ServerEndpoint注解声明的Websocket endpoint */ @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } } 加入连接发送消

    2024年04月15日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包