首页 > 其他分享 >@Transactional和try catch【reggie_take_out】

@Transactional和try catch【reggie_take_out】

时间:2023-01-14 09:22:05浏览次数:47  
标签:irun2u Transactional 菜品 private try take reggie import com

https://blog.csdn.net/manonggeerdan/article/details/124959685
https://gitee.com/yub4by/my-reggie-take-out

package com.irun2u.reggie.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.irun2u.reggie.common.CustomException;
import com.irun2u.reggie.dto.DishDto;
import com.irun2u.reggie.entity.Dish;
import com.irun2u.reggie.entity.DishFlavor;
import com.irun2u.reggie.mapper.DishMapper;
import com.irun2u.reggie.service.DishFlavorService;
import com.irun2u.reggie.service.DishService;
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;

/**
 * @Author: haifei
 * @Date: 2023/1/7 13:51
 */
@Service
public class DishServiceImpl extends ServiceImpl<DishMapper, Dish> implements DishService {

    @Autowired
    private DishFlavorService dishFlavorService;

    /**
     * 新增菜品
     * 同时插入菜品对应的口味数据
     * 需要操作两张表:dish、dish_flavor
     * 因为涉及两张表,这里还要加入事务进行控制,防止多表操作崩溃
     *
     * @Transactional和try catch的使用方法
     * https://blog.csdn.net/manonggeerdan/article/details/124959685
     * @param dishDto
     */
    @Transactional //开启事务(启动类上+@EnableTransactionManagement)
    @Override
    public void saveWithFlavor(DishDto dishDto) {
        try {
            //保存到dish表
            this.save(dishDto);

            //保存到dish表就有了dishId
            Long dishId = dishDto.getId();

            //模拟出错测试事务回滚 //友好交互前台应该有所提示:throw new CustomException("新增菜品事务内异常")处理
//            int i = 1/0;

            //给每条falvor记录设置dishID(falvor从前端只封装了name和value)
            List<DishFlavor> flavors = dishDto.getFlavors();
        /*for (DishFlavor flavor : flavors) {
            flavor.setDishId(dishId);
        }*/
            flavors = flavors.stream().map((item) -> {
                item.setDishId(dishId);
                return item;
            }).collect(Collectors.toList());

            //保存到dish_flavor表
            dishFlavorService.saveBatch(flavors);
        } catch (Exception e) {
            throw new CustomException("新增菜品事务内异常");
        }
    }
}


package com.irun2u.reggie.common;

/**
 * @Author: haifei
 * @Date: 2023/1/12 17:22
 *
 * 自定义业务异常类
 */
public class CustomException extends RuntimeException{

    public CustomException(String msg){
        super(msg);
    }
}

package com.irun2u.reggie.common;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import java.sql.SQLIntegrityConstraintViolationException;


/**
 * @Author: haifei
 * @Date: 2023/1/5 16:50
 *
 * 全局异常处理
 * 基于代理实现,代理controller,通过aop拦截方法
 * 当出现异常时,统一来此处理
 */
@ControllerAdvice(annotations = {RestController.class, Controller.class}) //拦截加了@RestController或@Controller的类
@ResponseBody
@Slf4j
public class GlobalExceptionHandler {

    /**
     * 异常处理
     * 插入数据字段不可重复限制
     * @param ex
     * @return
     */
    @ExceptionHandler(SQLIntegrityConstraintViolationException.class)
    public R<String> exceptionHandler(SQLIntegrityConstraintViolationException ex){
        log.error(ex.getMessage());
        //Duplicate entry 'lisi' for key 'idx_username'
        if (ex.getMessage().contains("Duplicate entry")){
            String[] split = ex.getMessage().split(" ");
            String msg = split[2] + "已存在";
            return R.error(msg);
        }
        return R.error("未知错误");
    }

    /**
     * 处理自定义异常
     * 与CustomException配合
     * @param ex
     * @return
     */
    @ExceptionHandler(CustomException.class)
    public R<String> exceptionHandler(CustomException ex){
        log.error(ex.getMessage());
        return R.error(ex.getMessage());
    }
}



package com.irun2u.reggie.mapper;

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

/**
 * @Author: haifei
 * @Date: 2023/1/7 13:50
 */
@Mapper
public interface DishMapper extends BaseMapper<Dish> {
}

package com.irun2u.reggie.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.irun2u.reggie.dto.DishDto;
import com.irun2u.reggie.entity.Dish;

/**
 * @Author: haifei
 * @Date: 2023/1/7 13:50
 */
public interface DishService extends IService<Dish> {

    void saveWithFlavor(DishDto dishDto);

}

package com.irun2u.reggie.controller;

import com.irun2u.reggie.common.R;
import com.irun2u.reggie.dto.DishDto;
import com.irun2u.reggie.service.DishFlavorService;
import com.irun2u.reggie.service.DishService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

/**
 * @Author: haifei
 * @Date: 2023/1/7 13:49
 */
@Slf4j
@RestController
@RequestMapping("/dish")
@Api(tags = "菜品接口")
public class DishController {

    @Autowired
    private DishService dishService;

    @Autowired
    private DishFlavorService dishFlavorService;

    /**
     * 新增菜品功能前后端交互过程:
     * 1. add.html页面发送ajax请求,从服务端获取菜品分类数据并展示到下拉框中
     *      CategoryController/list()
     * 2. 页面发送请求进行图片上传,请求服务端将图片保存到服务器
     *      CommonController/upload()
     * 3. 页面发送请求进行图片下载,将上传的图片进行回显
     *      CommonController/download()
     * 4、点击保存按钮,发送ajax请求,将菜品相关数据以json形式提交到服务端
     *      DishController/save()
     *
     *      此处只用Dish接收不行了,因为前端add.html中传过来的json中不仅包含了Dish还包含了Flavor
     *      所以需要一个新类DishDTO(数据传输对象,用于展示层与服务层之间交互)来封装页面提交的数据
     */
    @ApiOperation("新增菜品")
    @PostMapping
    public R<String> save(@RequestBody DishDto dishDto){ //@RequestBody接收前端传来的json数据
        log.info(dishDto.toString());
        dishService.saveWithFlavor(dishDto);
        return R.success("新增菜品成功");
    }
}


package com.irun2u.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 io.swagger.annotations.Api;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;

/**
 * value–类名
 * description–描述
 */
@ApiModel(value = "Dish", description = "菜品实体")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Dish implements Serializable {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty("菜品id")
    private Long id;

    /**
     * value–字段说明
     * name–重写属性名字
     * dataType–重写属性类型
     * required–是否必填
     * example–举例说明
     * hidden–隐藏
     */
    @ApiModelProperty(value = "菜品名称", required = true, example = "鲁菜")
    private String name;


    @ApiModelProperty(value = "菜品分类id", required = false)
    private Long categoryId;


    @ApiModelProperty(value = "菜品价格", required = false)
    private BigDecimal price;


    @ApiModelProperty(value = "商品码", required = false)
    private String code;


    @ApiModelProperty(value = "菜品图片", required = false)
    private String image;


    @ApiModelProperty(value = "描述信息", required = false)
    private String description;


    @ApiModelProperty(value = "菜品状态(0 停售 1 起售)", required = false)
    private Integer status;


    @ApiModelProperty(value = "顺序", required = false)
    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;

}

package com.irun2u.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;


    //菜品id
    private Long dishId;


    //口味名称
    private String name;


    //口味数据list
    private 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;

}

package com.irun2u.reggie.dto;

import com.irun2u.reggie.entity.Dish;
import com.irun2u.reggie.entity.DishFlavor;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;

@Data
public class DishDto extends Dish {

    //继承了Dish:DishDto中拥有Dish的所有属性
    //相较Dish,DishDto又扩展了以下属性

    private List<DishFlavor> flavors = new ArrayList<>();

    //以下这俩暂时用不到
    private String categoryName;

    private Integer copies;
}

标签:irun2u,Transactional,菜品,private,try,take,reggie,import,com
From: https://www.cnblogs.com/yppah/p/17051267.html

相关文章

  • 【每日一读】GAGE: Geometry Preserving Attributed Graph Embeddings
    目录​​简介​​​​论文简介​​​​ABSTRACT​​​​1INTRODUCTION​​​​2PRELIMINARIES​​​​6CONCLUSIONS​​​​结语​​简介Hello!非常感谢您阅读海轰的文章......
  • match's mistake - 3
    等差数列(https://www.luogu.com.cn/problem/P8682)第一眼下去,好简单,结果交上去一个t,三个wa,还是不能小看蓝桥杯的模拟的废话不多说,开始解读题目首先题目很容易理解,给定一......
  • docker-compose up 启动容器服务超时错误:ERROR: An HTTP request took too long to co
    问题:    本人正在使用docker运行一个中型的项目,包含40多个微服务及相关数据库的docker。由于docker-composeup同时启动的服务过多,超过了请求HTTP限制的60s时间......
  • Java上的try catch并不影响性能
     先说结论,未有异常发生时,二者性能上几乎没有差别。trycatch关键字在编译器级别上的实现原理:1、类会跟随一张异常表(exceptiontable),每一个trycatch都会在这个表里......
  • 解决 OpenAI‘s API is not available in your country
    解决 OpenAI'sAPIisnotavailableinyourcountry.根据百度翻译,英文大意为:OpenAI的API在您所在的国家/地区不可用。根据显示,需要魔法网络  好了,我们可以看......
  • JavaScript 错误 throw、try、catch
    JavaScript错误throw、try、catchtry:语句测试代码的错误;catch:语句处理错误;throw:语句创建自定义错误;finally:语句在try和catch语句之后,无论是否有触发异常,该语句都会执行......
  • match's mistake-3
    乘法表(https://www.luogu.com.cn/problem/P8723)小题一道但是得注意几点1.给定的数据范围不存在第三位数2.不只是结果大于十的得转化字母乘法中的也要转化(如1010=91应......
  • match's mistake-2
    走方格(https://www.luogu.com.cn/problem/P8707)理解一下题目1.行和列都是偶数的时候不能走,问有多少种到达终点的方法看到题目的一瞬间,第一时间想到广搜,结果t了~悲伤~。......
  • try-with-resources 语法简介
    try-with-resources语法特点①资源说明头()中可以包含多个定义,用分号隔开(最后的分号可以省略)。资源说明头()中定义的每个对象都会在try块的末尾调用其close()。②try-wit......
  • match's mistake
    解码(https://www.luogu.com.cn/problem/P8706)题目看起来很简单(实际也很简单)注意几个点就好1.小明很有可能不写1或者写了一个0,所以判断的时候要从0去判断2.所有的例子......