Dark Horse Programmer Java Project Actual Combat "Regis Takeaway" Notas Día 3: Video P40-P48

Dark Horse Programmer Java Project Actual Combat "Regis Takeaway" Notas

Este curso se basa en el popular negocio actual de pedidos de comida para llevar, y el negocio es real, práctico y extenso. Desarrollado en base a marcos técnicos populares como Spring Boot y mybatis plus, lo que lleva a los estudiantes a experimentar el proceso real de desarrollo de proyectos, el proceso de análisis de requisitos y el proceso de implementación de código. Después de completar este curso, puede obtener: ejercitar la capacidad de análisis de demanda, la capacidad de codificación, la capacidad de depuración de errores y aumentar la experiencia de desarrollo.

  • Enlace: https://www.bilibili.com/video/BV13a411q753

20230320 Día 3: Vídeo P40-P48

  • autocompletar campo público
  • Añadir categoría
  • Consulta de paginación de información de clasificación
  • eliminar categoría
  • modificar clasificación

Los campos comunes se autocompletan:

análisis del problema:

Anteriormente, hemos completado el desarrollo de la función de gestión de empleados del sistema en segundo plano. Al agregar un nuevo empleado, debe configurar campos como la hora de creación, el creador, la hora de modificación y la persona de modificación. Al editar un empleado, debe para establecer la hora de modificación y la persona de modificación. Estos campos son campos públicos, es decir, muchas tablas tienen estos campos. ¿Se pueden procesar estos campos públicos de manera uniforme en algún lugar para simplificar el desarrollo?
La respuesta es utilizar la función de autorrelleno de campos públicos proporcionada por Mybatis Plus.

Código:

Los campos públicos de Mybatis Plus se rellenan automáticamente, es decir, asignando valores específicos a campos específicos al insertar o actualizar.La ventaja de usarlo es que
estos campos se pueden procesar de manera uniforme, evitando la duplicación de código.
Pasos de implementación:
1. Agregue la anotación @TableField al atributo de la clase de entidad para especificar la estrategia de llenado automático
2. Escriba el controlador de objetos de metadatos de acuerdo con los requisitos del marco y asigne valores a los campos públicos en esta clase. la clase necesita implementar la interfaz MetaObjectHandler

Cree una nueva clase MyMetaObjectHandler bajo el paquete común, herede la interfaz MetaObjectHandler e implemente los dos métodos de insertFill y updateFill

package com.raggie.common;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;

public class MyMetaObjectHandler implements MetaObjectHandler {
    
    
    @Override
    public void insertFill(MetaObject metaObject) {
    
    
        
    }

    @Override
    public void updateFill(MetaObject metaObject) {
    
    

    }
}

Agregue comentarios a la tarea que involucre información pública en EmployeeController

@PostMapping
public R<String> save(HttpServletRequest request,@RequestBody Employee employee){
    
    
    //设置初始密码为123456,进行md5加密处理
    employee.setPassword(DigestUtils.md5DigestAsHex("123456".getBytes()));

//        employee.setCreateTime(LocalDateTime.now());
//        employee.setUpdateTime(LocalDateTime.now());
//        Long empID = (Long) request.getSession().getAttribute("employee");
//        employee.setCreateUser(empID);
//        employee.setUpdateUser(empID);

    employeeService.save(employee);

    log.info("新增员工,员工信息:{}",employee.toString());
    return R.success("新增员工成功!");
}
@PutMapping
public  R<String> update(HttpServletRequest request,@RequestBody Employee employee){
    
    
    log.info(employee.toString ());
//        Long empID = (Long) request.getSession().getAttribute("employee");
//        employee.setUpdateUser(empID);
//        employee.setUpdateTime(LocalDateTime.now());
    employeeService.updateById(employee);
    log.info("员工信息修改为:{}",employee.toString());
    return R.success("员工信息修改成功!");
}

Establecer la asignación de propiedades de autocompletar en MyMetaObjectHandler

package com.raggie.common;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

/**
 * 自定义元数据处理器
 */
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    
    
    @Override
    public void insertFill(MetaObject metaObject) {
    
    
        log.info("公共字段自动填充[insert]...");
        log.info(metaObject.toString());

        metaObject.setValue("createTime",LocalDateTime.now());
        metaObject.setValue("updateTime",LocalDateTime.now());

        metaObject.setValue("createUser",new Long(1));
        metaObject.setValue("updateUser",new Long(1));
    }

    @Override
    public void updateFill(MetaObject metaObject) {
    
    
        log.info("公共字段自动填充[update]...");
        log.info(metaObject.toString());
        metaObject.setValue("updateTime",LocalDateTime.now());
        metaObject.setValue("updateUser",new Long(1));
    }
}

Nota: actualmente configuramos createUser y updateUser: como valores fijos, debemos modificarlos para obtener dinámicamente la identificación del usuario que ha iniciado sesión actualmente

Función perfecta:

Hemos completado el desarrollo del código de la función de llenado automático de campos públicos antes, pero todavía hay un problema que no se ha resuelto, es decir, la identificación de usuario que configuramos cuando llenamos automáticamente createUser y updateUser es un valor fijo, y ahora necesita transformarlo para obtener dinámicamente el usuario de inicio de sesión actual
.id. Algunos estudiantes pueden pensar que después de que el usuario inicia sesión correctamente, almacenamos la identificación del usuario en HttpSession. ¿Ahora puedo obtenerla de HttpSession?
Tenga en cuenta que no podemos obtener el objeto HttpSession en la clase MyMetaObjectHandler, por lo que debemos obtener la identificación del usuario de inicio de sesión de otras formas. Puede usar ThreadLocal para resolver este problema, que es una clase proporcionada en DK.

Pasos de implementación:

1. Escriba la clase BaseContext.tool, basada en la clase de herramienta del paquete ThreadLocal
2. Llame a BaseContext en el método doFilter de LoginCheckFilter para establecer la identificación del usuario actualmente conectado
3. Llame a BaseContext en el método de MyMetaObjectHandler para obtener la identificación del usuario registrado

Cree una nueva clase de herramienta BaseContext en el paquete común para llamar a ThreadLocal para guardar la identificación del usuario

package com.raggie.common;

/**
 * 基于ThreadLocal封装工具类,用于保存id
 */
public class BaseContext {
    
    
    private  static ThreadLocal<Long> threadLocal = new ThreadLocal<>();

    public static void setCurrentId(Long id) {
    
    
        threadLocal.set(id);
    }
    public static Long getCurrentId(){
    
    
        return threadLocal.get();
    }
}

Regrese a MyMetaObjectHandler, modifique updateUser y createUser, y llame a BaseContext para obtener el valor de id.

package com.raggie.common;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

/**
 * 自定义元数据处理器
 */
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    
    
    @Override
    public void insertFill(MetaObject metaObject) {
    
    
        log.info("公共字段自动填充[insert]...");
        log.info(metaObject.toString());

        metaObject.setValue("createTime",LocalDateTime.now());
        metaObject.setValue("updateTime",LocalDateTime.now());

        metaObject.setValue("createUser",BaseContext.getCurrentId());
        metaObject.setValue("updateUser",BaseContext.getCurrentId());
    }

    @Override
    public void updateFill(MetaObject metaObject) {
    
    
        log.info("公共字段自动填充[update]...");
        log.info(metaObject.toString());

        metaObject.setValue("updateTime",LocalDateTime.now());
        metaObject.setValue("updateUser",BaseContext.getCurrentId());
    }
}

Nueva categoría:

análisis de la demanda:

La información de clasificación se puede gestionar en el sistema de fondo, y la clasificación incluye dos tipos, a saber, la clasificación de platos y la clasificación de comidas preparadas. Cuando agregamos un plato en el sistema de fondo, debemos
seleccionar una categoría de plato. Cuando agregamos un menú fijo en el sistema de fondo, debemos seleccionar una categoría de menú fijo. Los platos y menús fijos correspondientes también se mostrarán en la pantalla. terminal móvil según clasificación de plato y
clasificación de comida establecida.combo.

Antes de desarrollar funciones comerciales, primero cree la estructura básica de clases e interfaces que deben usarse:

  • Categoría de clase de entidad (importar directamente desde los materiales del curso)
package com.raggie.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 lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.time.LocalDateTime;

/**
 * 分类
 */
@Data
public class Category implements Serializable {
    
    

    private static final long serialVersionUID = 1L;

    private Long id;


    //类型 1 菜品分类 2 套餐分类
    private Integer type;


    //分类名称
    private String name;


    //顺序
    private Integer sort;


    //创建时间
    @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;

}
  • Asignador: Asignador de categorías de interfaz
package com.raggie.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.raggie.entity.Category;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface CategoryMapper extends BaseMapper<Category> {
    
    

}

  • Interfaz de capa empresarial CategoryService
package com.raggie.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.raggie.entity.Category;

public interface CategoryService extends IService<Category> {
    
    

}

  • Clase de implementación de capa empresarial CategoryServicelmpl
package com.raggie.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.raggie.entity.Category;
import com.raggie.mapper.CategoryMapper;
import com.raggie.service.CategoryService;
import org.springframework.stereotype.Service;

@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService {
    
    

}

  • Capa de control CategoryController
package com.raggie.controller;

import com.raggie.service.CategoryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Slf4j
@RequestMapping("/category")
public class CategoryController {
    
    
    @Autowired
    private CategoryService categoryService;

}

Cree un método de guardado en CategoryController para guardar la información del plato y agregue la anotación @PostMapping.
Llame al método save de categoryService para guardar la información y llame a R.success para devolver la información de éxito de la operación al front-end.

@PostMapping()
public R<String> save(@RequestBody Category category) {
    
    
    categoryService.save(category);
    log.info("菜品保存成功,信息为:{}",category.toString());
    return R.success("菜品保存成功!");
}

Consulta de paginación de información de clasificación:

Cree un nuevo método de página en CategoryController, similar a la consulta de la página de empleados

@GetMapping("/page")
public R<Page> page(int page, int pageSize){
    
    
    log.info("接收到查询请求,page={},pagesize={},name={}",page,pageSize);
    //构造分页构造器
    Page pageinfo=new Page(page,pageSize);
    //构造条件构造器
    LambdaQueryWrapper<Category> queryWrapper = new LambdaQueryWrapper();
    //添加排序条件
    queryWrapper.orderByAsc(Category::getSort);
    //执行查询
    categoryService.page(pageinfo,queryWrapper);
    return R.success(pageinfo);
    }

Eliminar categoría:

desarrollo de código

Antes de desarrollar el código, debe ordenar el proceso de ejecución de todo el programa:
1. La página envía una solicitud ajax y envía el parámetro (id) al servidor
2. El controlador del servidor recibe los datos enviados por la página y llama el Servicio para borrar los datos
3. El Servicio llama al Mapeador Operar la base de datos

Cree un nuevo método Delete en CategoryController y llame al método removeById de categoryService

@DeleteMapping()
public R<String> delete(Long id){
    
    
    log.info("分类{}删除成功",id);
    categoryService.removeById(id);
    return R.success("分类删除成功!");
}

función perfecta

Anteriormente implementamos la función de eliminar categorías deslizando el dedo, pero no verificamos si las categorías eliminadas están asociadas a platos o comidas preparadas, por lo que debemos mejorar la función
.

Para mejorar la función de eliminación de categorías, primero debe preparar las clases e interfaces básicas:
1. Clases de entidad Plato y Comida preparada (simplemente copie de los materiales del curso)

package com.raggie.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.math.BigDecimal;
import java.time.LocalDateTime;

/**
 * 套餐
 */
@Data
public class Setmeal implements Serializable {
    
    

    private static final long serialVersionUID = 1L;

    private Long id;


    //分类id
    private Long categoryId;


    //套餐名称
    private String name;


    //套餐价格
    private BigDecimal price;


    //状态 0:停用 1:启用
    private Integer status;


    //编码
    private String code;


    //描述信息
    private String description;


    //图片
    private String image;


    @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;
}

package com.raggie.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.math.BigDecimal;
import java.time.LocalDateTime;

/**
 菜品
 */
@Data
public class Dish implements Serializable {
    
    

    private static final long serialVersionUID = 1L;

    private Long id;


    //菜品名称
    private String name;


    //菜品分类id
    private Long categoryId;


    //菜品价格
    private BigDecimal price;


    //商品码
    private String code;


    //图片
    private String image;


    //描述信息
    private String description;


    //0 停售 1 起售
    private Integer status;


    //顺序
    private Integer sort;


    @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. Interfaz Mapperi DishMapper y SetmealMapper

package com.raggie.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.raggie.entity.Dish;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface DishMapper extends BaseMapper<Dish> {
    
    

}

package com.raggie.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.raggie.entity.Setmeal;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface SetmealMapper extends BaseMapper<Setmeal> {
    
    
    
}

3. Servicio: conéctese a ▣DishService y SetmealService

package com.raggie.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.raggie.entity.Dish;

public interface DishService extends IService<Dish> {
    
    

}


package com.raggie.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.raggie.entity.Setmeal;

public interface SetmealService extends IService<Setmeal> {
    
    

}

4. Servicio: implementar clases DishServicelmpli y SetmealServicelmpl

package com.raggie.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.raggie.entity.Dish;
import com.raggie.mapper.DishMapper;
import com.raggie.service.DishService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

@Service
@Slf4j
public class DishServiceImpl extends ServiceImpl<DishMapper, Dish> implements DishService {
    
    
    
}

package com.raggie.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.raggie.entity.Setmeal;
import com.raggie.mapper.SetmealMapper;
import com.raggie.service.SetmealService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

@Service
@Slf4j
public class SetmealServiceImpl extends ServiceImpl<SetmealMapper, Setmeal>implements SetmealService {
    
    
    
}

Crear método de eliminación en CategoryService

package com.raggie.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.raggie.entity.Category;

public interface CategoryService extends IService<Category> {
    
    
    public void remove(Long id);

}

Llame a DishService y SetmealService en CategoryServiceImpl

private DishService dishService;
private SetmealService setmealService;

Consultar si la categoría actual está asociada con platos y, de ser así, lanzar una excepción comercial

LambdaQueryWrapper<Dish> dishLambdaQueryWrapper = new LambdaQueryWrapper<>();
dishLambdaQueryWrapper.eq(Dish::getCategoryId,id);
int count = dishService.count(dishLambdaQueryWrapper);
if(count>0){
    
    
    //已经关联了菜品

}

Consulta si la categoría actual está asociada con un paquete, si ya está relacionado, lanza una excepción comercial

LambdaQueryWrapper<Setmeal> setmealLambdaQueryWrapper = new LambdaQueryWrapper<>();
setmealLambdaQueryWrapper.eq(Setmeal::getCategoryId,id);
count = setmealService.count(setmealLambdaQueryWrapper);
if(count>0){
    
    
    //已经关联了套餐
    
}

Si no hay asociación, llame a removeById para eliminar la categoría

super.removeById(id);

Cree una clase de excepción comercial personalizada CustomException en común y herede RuntimeException

package com.raggie.common;

public class CustomException extends RuntimeException{
    
    
    public CustomException(String message){
    
    
        super(message);
    }
}

Se lanza una excepción en el método remove

public void remove(Long id) {
    
    
    //查询当前分类是否关联了菜品,如果已经关联,抛出一个业务异常
    LambdaQueryWrapper<Dish> dishLambdaQueryWrapper = new LambdaQueryWrapper<>();
    dishLambdaQueryWrapper.eq(Dish::getCategoryId,id);
    int count = dishService.count(dishLambdaQueryWrapper);
    if(count>0){
    
    
        //已经关联了菜品
        throw new CustomException("当前分类下关联了菜品");
    
    }
    //查询当前分类是否关联了套餐,如果已经关朕,抛出一个业务异常
    LambdaQueryWrapper<Setmeal> setmealLambdaQueryWrapper = new LambdaQueryWrapper<>();
    setmealLambdaQueryWrapper.eq(Setmeal::getCategoryId,id);
    int count2 = setmealService.count(setmealLambdaQueryWrapper);
    if(count2>0){
    
    
        //已经关联了套餐
        throw new CustomException("当前分类下关联了套餐");
    }
    //
    super.removeById(id);
    }

Crear un método de manejo de excepciones en CustomException

@ExceptionHandler(CustomException.class)
public R<String> exceptionHandler(CustomException ex){
    
    
    log.error(ex.getMessage());
    return R.error(ex.getMessage());
}

De vuelta en CategoryController, llame al método de eliminación recién modificado en eliminar para eliminar la categoría

public R<String> delete(Long id){
    
    
    log.info("分类{}删除成功",id);
    categoryService.remove(id);

    return R.success("分类删除成功!");
}

Modificar clasificación:

análisis de la demanda

Haga clic en el botón modificar en la página de la lista de administración de categorías, y aparecerá la ventana de modificación, repetirá la información de clasificación en la ventana de modificación y modifíquela, y finalmente haga clic en el botón Aceptar para completar la operación de modificación

Cree un método de actualización en CategoryController, agregue la anotación @PutMapping, llame al método updateById de categoryService para modificar la información de clasificación y devuelva el valor

@PutMapping
public R<String> update(@RequestBody Category category){
    
    
    log.info("修改分类信息:{}",category.toString());
    categoryService.updateById(category);
    R.success("修改分类信息成功!");
}

Supongo que te gusta

Origin blog.csdn.net/m0_46504802/article/details/129679914
Recomendado
Clasificación