Dark Horse Programmer Java Project Actual Combat "Regis Takeaway" Notes Day3: Video P40-P48

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

This course is based on the current popular takeaway food ordering business, and the business is real, practical and extensive. Developed based on popular technical frameworks such as Spring Boot and mybatis plus, leading students to experience the real project development process, requirements analysis process and code implementation process. After completing this course, you can gain: exercise demand analysis ability, coding ability, bug debugging ability, and increase development experience.

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

20230320 Day3: Video P40-P48

  • public field autofill
  • Add category
  • Classification information pagination query
  • delete category
  • modify classification

Common fields are auto-filled:

problem analysis:

Previously, we have completed the development of the employee management function of the background system. When adding a new employee, you need to set the fields such as creation time, creator, modification time, and modification person. When editing an employee, you need to set the modification time and modification person. These fields are public fields, that is, many tables have these fields. Can these public fields be processed uniformly somewhere to simplify development?
The answer is to use the public field autofill function provided by Mybatis Plus.

Code:

Mybatis Plus public fields are automatically populated, that is, assigning specified values ​​to specified fields when inserting or updating. The advantage of using it is that
these fields can be processed uniformly, avoiding duplication of code.
Implementation steps:
1. Add the @TableField annotation to the attribute of the entity class to specify the automatic filling strategy
2. Write the metadata object handler according to the framework requirements, and assign values ​​to the public fields in this class. This class needs to implement the MetaObjectHandler interface

Create a new MyMetaObjectHandler class under the common package, inherit the MetaObjectHandler interface, and implement the two methods of insertFill and 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) {
    
    

    }
}

Add comments to the assignment involving public information in 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("员工信息修改成功!");
}

Set autofill property assignment in 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));
    }
}

Note: Currently we set createUser and updateUser: as fixed values, we need to modify them to dynamically obtain the id of the currently logged-in user

Perfect function:

We have completed the code development of the automatic filling function of public fields before, but there is still a problem that has not been solved, that is, the user id we set when automatically filling createUser and updateUser is a fixed value, and now we need to transform it to dynamically obtain the current login user
. id. Some students may think that after the user logs in successfully, we store the user id in the HttpSession. Now I can get it from the HttpSession?
Note that we cannot obtain the HttpSession object in the MyMetaObjectHandler class, so we need to obtain the login user id in other ways. You can use ThreadLocal to solve this problem, which is a class provided in DK.

Implementation steps:

1. Write the BaseContext.tool class, based on the ThreadLocal package tool class
2. Call BaseContext in the doFilter method of LoginCheckFilter to set the id of the currently logged-in user
3. Call BaseContext in the method of MyMetaObjectHandler to obtain the id of the logged-in user

Create a new tool class BaseContext in the common package to call ThreadLocal to save the user id

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();
    }
}

Go back to MyMetaObjectHandler, modify updateUser and createUser, and call BaseContext to get the id value

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());
    }
}

New category:

demand analysis:

The classification information can be managed in the background system, and the classification includes two types, namely, the classification of dishes and the classification of set meals. When we add dishes in the background system, we need
to select a dish category. When we add a set meal in the background system, we need to select a set meal category. The corresponding dishes and set menus will also be displayed on the mobile terminal according to the dish classification and
set meal combo.

Before developing business functions, first create the basic structure of classes and interfaces that need to be used:

  • Entity class Category (import directly from the course materials)
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;

}
  • Mapper: Interface CategoryMapper
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> {
    
    

}

  • Business layer interface CategoryService
package com.raggie.service;

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

public interface CategoryService extends IService<Category> {
    
    

}

  • Business layer implementation class 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 {
    
    

}

  • Control layer 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;

}

Create a save method in CategoryController to save dish information and add @PostMapping annotation.
Call the save method of categoryService to save the information, and call R.success to return the operation success information to the front end.

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

Classification information pagination query:

Create a new Page method in CategoryController, similar to employee page query

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

Delete category:

code development

Before developing the code, you need to sort out the execution process of the entire program:
1. The page sends an ajax request and submits the parameter (id) to the server
2. The server controller receives the data submitted by the page and calls the Service to delete the data
3. The Service calls the Mapper Operate the database

Create a new Delete method in CategoryController and call the removeById method of categoryService

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

Perfect function

Previously, we have implemented the function of deleting categories by swiping, but we have not checked whether the deleted categories are associated with dishes or set meals, so we need to improve the function
.

To improve the category deletion function, you need to prepare basic classes and interfaces first:
1. Entity classes Dish and Setmeal (just copy from the course materials)

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. Mapperi interface DishMapper and 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. Service: connect to ▣DishService and 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. Service: implement classes DishServicelmpli and 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 {
    
    
    
}

Create remove method in 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);

}

Call DishService and SetmealService in CategoryServiceImpl

private DishService dishService;
private SetmealService setmealService;

Query whether the current category is associated with dishes, and if so, throw a business exception

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

}

Query whether the current category is associated with a package, if it is already related, throw a business exception

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

If there is no association, call removeById to delete the category

super.removeById(id);

Create a custom business exception class CustomException in common and inherit RuntimeException

package com.raggie.common;

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

An exception is thrown in the remove method

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

Create an exception handling method in CustomException

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

Back in CategoryController, call the just-modified remove method in delete to delete the category

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

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

Modify classification:

demand analysis

Click the modify button on the category management list page, and the modification window will pop up, echo the classification information in the modification window and modify it, and finally click the OK button to complete the modification operation

Create an update method in CategoryController, add the @PutMapping annotation, call the updateById method of categoryService to modify the classification information, and return the value

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

Guess you like

Origin blog.csdn.net/m0_46504802/article/details/129679914