基于Springboot外卖系统14:菜品新增模块+多个数据表操作+文件上传下载复用

2.1 需求分析

后台系统中可以管理菜品信息,通过新增功能来添加一个新的菜品,在添加菜品时需要选择当前菜品所属的菜品分类,并且需要上传菜品图片,在移动端会按照菜品分类来展示对应的菜品信息 。

2.2 数据模型

新增菜品,其实就是将新增页面录入的菜品信息插入到dish表,如果添加了口味做法,还需要向dish_flavor表插入数据。

表结构说明
dish菜品表
dish_flavor菜品口味表

 1). 菜品表:dish

 2). 菜品口味表:dish_flavor

2.3 准备工作

1). 实体类 DishFlavor

package com.itheima.reggie.entity;import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;/**
菜品口味*/
@Data
public class DishFlavor implements Serializable {private static final long serialVersionUID = 1L;private Long id;//菜品idprivate Long dishId;//口味名称private String name;//口味数据listprivate String value;@TableField(fill = FieldFill.INSERT)private LocalDateTime createTime;@TableField(fill = FieldFill.INSERT_UPDATE)private LocalDateTime updateTime;@TableField(fill = FieldFill.INSERT)private Long createUser;@TableField(fill = FieldFill.INSERT_UPDATE)private Long updateUser;//是否删除private Integer isDeleted;}

2). Mapper接口DishFlavorMapper

package com.itheima.reggie.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.itheima.reggie.entity.DishFlavor;
import org.apache.ibatis.annotations.Mapper;@Mapper
public interface DishFlavorMapper extends BaseMapper<DishFlavor> {
}

 3). 业务层接口 DishFlavorService

package com.itheima.reggie.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.itheima.reggie.entity.DishFlavor;public interface DishFlavorService extends IService<DishFlavor> {
}

 4). 业务层实现类 DishFlavorServiceImpl

package com.itheima.reggie.service.impl;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.reggie.entity.DishFlavor;
import com.itheima.reggie.mapper.DishFlavorMapper;
import com.itheima.reggie.service.DishFlavorService;
import org.springframework.stereotype.Service;/*** Description: new java files header..** @author w* @version 1.0* @date 2022/8/18 11:07*/
@Service
public class DishFlavorServiceImpl extends ServiceImpl<DishFlavorMapper, DishFlavor> implements DishFlavorService {
}

2.4 前端页面分析

2.4.1 新增菜品时前端页面和服务端的交互过程

1). 点击新建菜品按钮, 访问页面(backend/page/food/add.html), 页面加载时发送ajax请求,请求服务端获取菜品分类数据并展示到下拉框中

2). 页面发送请求进行图片上传,请求服务端将图片保存到服务器(上传功能已实现)

3). 页面发送请求进行图片下载,将上传的图片进行回显(下载功能已实现)

 4). 点击保存按钮,发送ajax请求,将菜品相关数据以json形式提交到服务端

页面代码:

 浏览器抓取请求:

开发新增菜品功能,其实就是在服务端编写代码去处理前端页面发送的这4次请求(上传、下载已实现)即可。经过上述的分析,还需要在服务端实现两块功能:

A. 菜品分类数据列表查询, 具体请求信息整理如下 :

请求说明
请求方式GET
请求路径/category/list
请求参数?type=1

B. 保存菜品信息, 具体请求信息整理如下 :

请求说明
请求方式POST
请求路径/dish
请求参数json格式

2.5 代码实现

2.5.1 菜品分类查询

在CategoryController中增加方法实现菜品分类查询,根据分类进行查询,并对查询的结果按照sort排序字段进行升序排序,如果sort相同,再按照修改时间倒序排序。

package com.itheima.reggie.controller;import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.reggie.common.R;
import com.itheima.reggie.entity.Category;
import com.itheima.reggie.service.CategoryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.util.List;/*** Description: 分类管理*/@RestController
@RequestMapping("/category")
@Slf4j
public class CategoryController {@Autowiredprivate CategoryService categoryService;/**@Description: 新增分类* @author LiBiGo* @date 2022/8/15 14:05*/@PostMappingpublic R<String> save(@RequestBody Category category){log.info("category:{}",category);categoryService.save(category);return R.success("新增分类成功");}@GetMapping("/page")public R<Page> page(int page,int pageSize){/**@Description: 分页查询* @author LiBiGo* @date 2022/8/15 14:21*/// 分页构造Page<Category> pageinfo = new Page<>(page,pageSize);// 构造条件构造器对象LambdaQueryWrapper<Category> queryWrapper = new LambdaQueryWrapper();// 添加排序条件,根据sore进行排序queryWrapper.orderByAsc(Category::getSort);// 进行分页查询categoryService.page(pageinfo,queryWrapper);return R.success(pageinfo);}@DeleteMappingpublic R<String> delete(Long id){/**@Description: 根据id删除分类* @author LiBiGo* @date 2022/8/16 9:58*/log.info("删除分类,id为{}",id);categoryService.remove(id);return R.success("分类信息删除成功");}@PutMappingpublic  R<String> update(@RequestBody Category category){/**@Description: 根据id修改分类信息* @author LiBiGo* @date 2022/8/16 10:49*/log.info("根据id修改分类信息:{}",category);categoryService.updateById(category);return R.success("修改分类成功");}@GetMapping("/list")public R<List<Category>> list(Category category){/**@Description: 根据条件查询分类数据* @author LiBiGo* @date 2022/8/18 11:24*/// 条件构造器LambdaQueryWrapper<Category> queryWrapper =  new LambdaQueryWrapper<>();// 添加条件queryWrapper.eq(category.getType() != null,Category::getType,category.getType());// 添加排序条件queryWrapper.orderByAsc(Category::getSort).orderByDesc(Category::getUpdateTime);List<Category> list = categoryService.list(queryWrapper);return R.success(list);}
}

 代码编写完毕之后,我们可以打开新增菜品页面,查看响应的数据,及页面下拉列表的渲染情况:

2.5.2 保存菜品信息

在上述的分析中,在保存菜品页面传递过来的是json格式数据,格式如下:

{"name":"佛跳墙","price":88800,"code":"","image":"da9e1c70-fc32-4781-9510-a1c4ccd2ff59.jpg","description":"佛跳墙","status":1,"categoryId":"1397844357980663809","flavors":[{"name":"辣度","value":"[\"不辣\",\"微辣\",\"中辣\",\"重辣\"]","showOption":false},{"name":"忌口","value":"[\"不要葱\",\"不要蒜\",\"不要香菜\",\"不要辣\"]","showOption":false}]
}

存在问题:如果使用菜品类Dish来封装,只能封装菜品的基本属性,flavors属性是无法封装的。

解决方案:需要自定义一个实体类,然后继承自 Dish,并对Dish的属性进行拓展,增加 flavors 集合属性(内部封装DishFlavor)。

1). 导入 DishDto 实体类

封装页面传递的请求参数。

package com.itheima.reggie.dto;import com.itheima.reggie.entity.Dish;
import com.itheima.reggie.entity.DishFlavor;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;@Data
public class DishDto extends Dish {private List<DishFlavor> flavors = new ArrayList<>();private String categoryName;private Integer copies;
}

拓展: 我们在做项目时,经常会涉及到各种类型的实体模型。基本包含以下几种

实体模型描述
DTOData Transfer Object(数据传输对象),一般用于展示层与服务层之间的数据传输。
Entity最常用实体类,基本和数据表一一对应,一个实体类对应一张表。
VOValue Object(值对象), 主要用于封装前端页面展示的数据对象,用一个VO对象来封装整个页面展示所需要的对象数据
POPersistant Object(持久层对象), 是ORM(Objevt Relational Mapping)框架中Entity,PO属性和数据库中表的字段形成一一对应关系

2). DishController定义方法新增菜品

在该Controller的方法中,不仅需要保存菜品的基本信息,还需要保存菜品的口味信息,需要操作两张表,所以需要在DishService接口中定义接口方法,在这个方法中需要保存上述的两部分数据。

package com.itheima.reggie.controller;import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.itheima.reggie.common.R;
import com.itheima.reggie.dto.DishDto;
import com.itheima.reggie.service.DishFlavorService;
import com.itheima.reggie.service.DishService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** Description: 菜品管理 菜品及菜品口味的相关操作,统一使用这一个controller即可。* @version 1.0* @date 2022/8/18 11:08*/@Slf4j
@RestController
@RequestMapping("/dish")
public class DishController {@Autowiredprivate DishService dishService;@Autowiredprivate DishFlavorService dishFlavorService;@PostMappingpublic R<String> save(@RequestBody DishDto dishDto){/**@Description: 新增菜品* @author LiBiGo* @date 2022/8/18 11:44*/log.info(dishDto.toString());dishService.saveWithFlavor(dishDto);return R.success("新增菜品成功");}}

 3). DishService中增加方法saveWithFlavor

package com.itheima.reggie.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.itheima.reggie.dto.DishDto;
import com.itheima.reggie.entity.Dish;public interface DishService extends IService<Dish> {// 新增菜品,需要同时插入菜品对应的口味数据,需要操作两张表,dish、dish_flavorpublic void saveWithFlavor(DishDto dishDto);}

 4). DishServiceImpl中实现方法saveWithFlavor

页面传递的菜品口味信息,仅仅包含name 和 value属性,缺少一个非常重要的属性dishId, 所以在保存完菜品的基本信息后,我们需要获取到菜品ID,然后为菜品口味对象属性dishId赋值。

具体逻辑如下:

①. 保存菜品基本信息 ;

②. 获取保存的菜品ID ;

③. 获取菜品口味列表,遍历列表,为菜品口味对象属性dishId赋值;

④. 批量保存菜品口味列表;

代码实现如下:

package com.itheima.reggie.service.impl;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.reggie.dto.DishDto;
import com.itheima.reggie.entity.Dish;
import com.itheima.reggie.entity.DishFlavor;
import com.itheima.reggie.mapper.DishMapper;
import com.itheima.reggie.service.DishFlavorService;
import com.itheima.reggie.service.DishService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import java.util.List;
import java.util.stream.Collectors;/*** Description: new java files header..** @author w* @version 1.0* @date 2022/8/16 10:15*/
@Service
@Slf4j
public class DishServiceImpl extends ServiceImpl<DishMapper,Dish> implements DishService{@Autowiredprivate DishFlavorService dishFlavorService;@Override@Transactionalpublic void saveWithFlavor(DishDto dishDto) {/**@Description: 新增菜品 同时保存对应的口味数据* @author LiBiGo* @date 2022/8/18 11:58*/// 保存菜品的基本信息到菜品表dishthis.save(dishDto);Long dishId = dishDto.getId(); // 菜品id// 菜品口味List<DishFlavor> flavors = dishDto.getFlavors();flavors = flavors.stream().map((item)->{item.setDishId(dishId);return item;}).collect(Collectors.toList());// 保存菜品口味数据到菜品口味表dish_flavordishFlavorService.saveBatch(flavors);}
}

5). 在引导类上加注解 @EnableTransactionManagement

Service层方法上加的注解@Transactional要想生效,需要在引导类上加上注解 @EnableTransactionManagement, 开启对事务的支持。

package com.itheima.reggie;import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.transaction.annotation.EnableTransactionManagement;@Slf4j //是lombok中提供的注解, 用来通过slf4j记录日志。
@SpringBootApplication // 启动类
// 需要在引导类上,加上Servlet组件扫描的注解,来扫描过滤器配置的@WebFilter注解,扫描后,使过滤器在运行时生效。
@ServletComponentScan //  扫描拦截器注解
@EnableTransactionManagement
public class ReggieApplication {/**@Description: 当搭建完上述的基础环境之后, 就可以通过引导类, 启动该项目。* @author LiBiGo* @date 2022/8/12 0:23*/public static void main(String[] args) {SpringApplication.run(ReggieApplication.class,args);log.info("项目启动成功............");}}

2.6 功能测试

代码编写完毕之后,我们重新启动服务,访问项目,然后登陆到系统中,进行菜品的新增测试,在测试时,我们可以通过debug断点跟踪的形式,查看我们传输的数据,及数据的封装。

 debug跟踪数据的封装情况:

然后在测试完毕后, 我们可以检查一下数据库中的数据保存情况:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/469015.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python层次聚类_python实现层次聚类

BAFIMINARMTO BA0662877255412996 FI6620295468268400 MI8772950754564138 NA2554687540219869 RM4122685642190669 TO9964001388696690 这是一个距离矩阵。不管是scipy还是fastcluster&#xff0c;都有一个计算距离矩阵的步骤&#xff08;也可以不用&#xff09;。距离矩阵是冗…

解析统计文本文件中的字符数、单词数、行数。

用android 编程解析统计文本文件中的字符数、单词数、行数&#xff08;作业&#xff09; 主要代码 ... private void analysis() { String str " "; int words 0; int chars 0; int lines 0; int spaces 0; int marks 0; int character 0; String filename e…

shell自动生成的文件有一个问号的后缀

写了一个脚本&#xff0c;自动处理一个文件。 rm -f session.log rm -f link wget ftp://hostname/f:/ddn/session.log egrep ^N[[:digit:]]|^D[1-4] session.log >>link egrep -c ^N[[:digit:]]|^D[1-4] session.log >>link egrep -v ACT/UP link>>link ls …

基于Springboot外卖系统15:菜品分页查询模块+根据类别ID填充类别信息

3.1 菜品分页查询功能需求分析 系统中的菜品数据很多的时候&#xff0c;如果在一个页面中全部展示出来会显得比较乱&#xff0c;不便于查看&#xff0c;所以一般的系统中都会以分页的方式来展示列表数据。 在菜品列表展示时&#xff0c;除了菜品的基本信息(名称、售价、售卖状…

python 3d渲染_python老司机带你玩玩炫酷的3D渲染,酷毙了!

自从学会了turtle模块后&#xff0c;画了不少简笔画。像小猪佩奇、哆啦A梦等等&#xff0c;但是这些依然不能让身边人感受到python的强大&#xff0c;依然是每次装逼必被打脸。就像你用turtle画了这个 别人拿出了这个 怎么办&#xff1f;面对函数库如此丰富的python&#xff0c…

Linux内存管理(最透彻的一篇)

摘要:本章首先以应用程序开发者的角度审视Linux的进程内存管理,在此基础上逐步深入到内核中讨论系统物理内存管理和内核内存的使用方法。力求从外到内、水到渠成地引导网友分析Linux的内存管理与使用。在本章最后,我们给出一个内存映射的实例,帮助网友们理解内核内存管理与…

基于Springboot外卖系统16:菜品修改模块+菜品信息回显+ID查询口味列表+组装数据并返回

4.1 菜品修改模块需求分析 在菜品管理列表页面点击修改按钮&#xff0c;跳转到修改菜品页面&#xff0c;在修改页面回显菜品相关信息并进行修改&#xff0c;最后点击确定按钮完成修改操作。 4.2 菜品修改模块前端页面&#xff08;add.html&#xff09;和服务端的交互过程 1).…

POJ - 2385 Apple Catching (dp)

题意&#xff1a;有两棵树&#xff0c;标号为1和2&#xff0c;在Tmin内&#xff0c;每分钟都会有一个苹果从其中一棵树上落下&#xff0c;问最多移动M次的情况下&#xff08;该人可瞬间移动&#xff09;&#xff0c;最多能吃到多少苹果。假设该人一开始在标号为1的树下。 分析&…

基于Springboot外卖系统17: 新增套餐模块+餐品信息回显+多数据表存储

1.1 新增套餐需求分析 后台系统中可以管理套餐信息&#xff0c;通过新增套餐功能来添加一个新的套餐&#xff0c;在添加套餐时需要选择当前套餐所属的套餐分类和包含的菜品&#xff0c;并且需要上传套餐对应的图片&#xff0c;在移动端会按照套餐分类来展示对应的套餐。 1.2 新…

cocoscreator editbox 只允许数字_用Cocos做一个数字调节框

点击上方蓝色字关注我们~当玩家购买道具的时候&#xff0c;一个个买可能会比较麻烦&#xff0c;用数字调节框的话玩家一次性就可以买好几十个了(钱够的话)。运行效果如下&#xff1a;Cocos Creator版本&#xff1a;2.2.0后台回复"数字调节框"&#xff0c;获取该项目完…

Android Jni 例程

1.Jni的作用 Java是一种比较高级的语言,Java调用c库,调用c++库是必不可少的,所以Jni就应运而生了。 NDK:NDK是Native Development Kit的缩写,是Google提供的一套工具集,可以让你其他语言(C、C++或汇编)开发 Android的 JNI。NDK可以编译多平台的so,开发人员只需要简单…

Xshell 无法连接虚拟机中的ubuntu的问题

转自&#xff1a;http://blog.csdn.net/qq_26941173/article/details/51173320版权声明&#xff1a;本文为博主原创文章&#xff0c;未经博主允许不得转载。 昨天在VMware Player中安装了ubuntu系统&#xff0c;今天想通过xshell连接ubuntu&#xff0c;结果显示 Connecting t…

基于Springboot外卖系统18:套餐分页查询模块+删除套餐+多数据表同步

1. 套餐分页查询模块 1.1 需求分析 系统中的套餐数据很多的时候&#xff0c;如果在一个页面中全部展示出来会显得比较乱&#xff0c;不便于查看&#xff0c;所以一般的系统中都会以分页的方式来展示列表数据。 在进行套餐数据的分页查询时&#xff0c;除了传递分页参数以外&a…

jsp项目开发案例_Laravel 中使用 swoole 项目实战开发案例一 (建立 swoole 和前端通信)life...

1 开发需要环境工欲善其事&#xff0c;必先利其器。在正式开发之前我们检查好需要安装的拓展&#xff0c;不要开发中发现这些问题&#xff0c;打断思路影响我们的开发效率。安装 swoole 拓展包安装 redis 拓展包安装 laravel5.5 版本以上如果你还不会用swoole就out了程序猿的生…

Service rootservice does not have a SELinux domain defined

新增一个SELINUX启动的时候出现问题 新增如下 service rootservice /system/bin/rootserviceuser rootgroup rootdisabledoneshoton property:sys.boot_completed1start rootservice具体补丁请查看文件 链接&#xff1a;https://pan.baidu.com/s/1AlBuXfdn-xFRwDwmsX4svA 提取…

Docker系列第01部分:介绍+虚拟化+什么是Decker+组件

0 应用部署难点 1.在软件开发中&#xff0c;最麻烦的事情之一就是环境配置。在正常情况下&#xff0c;如果要保证程序能运行&#xff0c;我们需要设置好操作系统&#xff0c;以及各种库和组件的安装。2.举例来说&#xff0c;要运行一个Python程序&#xff0c;计算机必须要有 P…

1.7.08:字符替换

08:字符替换 查看提交统计提问总时间限制: 1000ms内存限制: 65536kB描述把一个字符串中特定的字符全部用给定的字符替换&#xff0c;得到一个新的字符串。 输入只有一行&#xff0c;由一个字符串和两个字符组成&#xff0c;中间用单个空格隔开。字符串是待替换的字符串&#xf…

net.conn read 判断数据读取完毕_1.5 read, write, exit系统调用

接下来&#xff0c;我将讨论对于应用程序来说&#xff0c;系统调用长成什么样。因为系统调用是操作系统提供的服务的接口&#xff0c;所以系统调用长什么样&#xff0c;应用程序期望从系统调用得到什么返回&#xff0c;系统调用是怎么工作的&#xff0c;这些还是挺重要的。你会…

Android内核学习笔记

0、android系统启动 《Android系统启动流程 -- bootloader》 《The Android boot process from power on》 《Android 启动过程介绍》 《Android培训班(86)内核运行之前的引导程序》 这是一系列文章 《Android 分区挂载》 1、init 《深入理解android 卷1》 第3章 深入理解…

Docker系列第02部分:Docker安装与启动

1 安装环境说明 这里将Docker安装到CentOS上。注意&#xff1a;这里建议安装在CentOS7.x以上的版本&#xff0c;在CentOS6.x的版本中&#xff0c;安装前需要安装其他很多的环境而且Docker很多补丁不支持更新。 2 Docker安装与使用 2.0 windows安装 1 windows安装&#xff08…