菜品分类下拉列表
CategoryController里面写
/*** 根据条件查询分类数据** @param category* @return*/@GetMapping("/list")@ApiOperation("菜品分类目录")public R<List<Category>> list(Category category) {List<Category> list = categoryService.list(Wrappers.lambdaQuery(Category.class)//type=1,前端传过来的,就是查询类型为1的,1就是菜品不是套餐,2是套餐.eq(category.getType() != null, Category::getType, category.getType()).orderByDesc(Category::getUpdateTime));return R.success(list);}
保存菜品时要保存口味要操作两张表
我们可以看到在保存菜品时,页面传递过来的是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)。清楚了这一点之后,接下来就进行功能开发。
导入 DishDto 实体类
封装页面传递的请求参数。
所属包: com.itheima.reggie.dto
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;
}
拓展: 我们在做项目时,经常会涉及到各种类型的实体模型。基本包含以下几种
DTO | Data Transfer Object(数据传输对象),一般用于展示层与服务层之间的数据传输。 |
VO | Value Object(值对象), 主要用于封装前端页面展示的数据对象,用一个VO对象来封装整个页面展示所需要的对象数据 |
PO | Persistant Object(持久层对象), 是ORM(Objevt Relational Mapping)框架中Entity,PO属性和数据库中表的字段形成一一对应关系 |
新增菜品
DishController
private final DishService dishService;/*** 新增菜品** @param dishDto* @return*/@ApiOperation("新增菜品")@PostMappingpublic R<String> save(@RequestBody DishDto dishDto) {log.info(dishDto.toString());dishService.saveWithFlavor(dishDto);return R.success("新增菜品成功");}
DishService
//新增菜品,同时插入菜品对应的口味数据,需要操作两张表:dish、dish_flavorvoid saveWithFlavor(DishDto dishDto);
DishServiceImpl
private final DishFlavorService dishFlavorService;/*** 新增菜品,同时保存对应的口味数据*/@Transactionalpublic void saveWithFlavor(DishDto dishDto) {//保存菜品的基本信息到菜品表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);}
说明:
由于在 saveWithFlavor 方法中,进行了两次数据库的保存操作,操作了两张表,那么为了保证数据的一致性,我们需要在方法上加上注解 @Transactional来控制事务。
在引导类上加注解 @EnableTransactionManagement
Service层方法上加的注解@Transactional要想生效,需要在引导类上加上注解 @EnableTransactionManagement, 开启对事务的支持。
package com.itheima.reggie;import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.Environment;
import org.springframework.transaction.annotation.EnableTransactionManagement;import java.net.InetAddress;@Slf4j
@SpringBootApplication
@ServletComponentScan
@EnableTransactionManagement
public class ReggieApplication {public static void main(String[] args) {ConfigurableApplicationContext application = SpringApplication.run(ReggieApplication.class, args);Environment env = application.getEnvironment();String port = env.getProperty("server.port");log.info("\n----------------------------------------------------------\n\t" +"running success! Access URLs:\n\t" +"Local: \t\thttp://localhost:" + port +"/backend/page/login/login.html"+"\n\t" +"Swagger文档: \thttp://localhost:" + port + "/doc.html\n" +"----------------------------------------------------------");}
}