【JAVA学习】07-跟着黑马程序员课程敲全栈项目(四)
发表于:2024-03-27 |

前言

最近学习又有点懈怠了,想找个学习搭子一起互相督促学习。今天继续跟着黑马程序员的课程敲全栈项目。

公共字段自动填充

需求

  • 自定义注解AutoFill,用于标识需要进行公共字段自动填充的方法
  • 自定义切面类AutoFillAspect,统一拦截加入了AutoFill注解的方法,通过反射为公共字段赋值
  • 在Mapper的方法上加入AutoFill注解

代码

添加maven依赖

1
2
3
4
 <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>

添加自定义注解

注意这个文件类型是注解
com.sky.annotation.AutoFill

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import com.sky.enumeration.OperationType;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* ClassName: AutoFill
* Package: com.sky.annotation
* Description: 自定义注解,用于标识某个方法需要进行功能字段自动填充处理
*
* @Author codesigner
* @Create 2024/3/22 19:51
* @Version 1.0
*/
//这个注解只允许加在方法上
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoFill {
// 数据库操作类型:UPDATE INSERT
OperationType value();
}

添加切面类

com.sky.aspect.AutoFillAspect

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
package com.sky.aspect;

import com.sky.annotation.AutoFill;
import com.sky.constant.AutoFillConstant;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MemberSignature;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.time.LocalDateTime;

/**
* ClassName: AutoFillAspect
* Package: com.sky.aspect
* Description:自定义切面,实现公共字段自动填充处理逻辑
*
* @Author codesigner
* @Create 2024/3/22 20:00
* @Version 1.0
*/

@Aspect
@Component
@Slf4j
public class AutoFillAspect {

/**
* 切入点
*/
@Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
public void autoFillPointCut(){}


/**
* 前置通知,在通知中进行公共字段的赋值
* */
@Before("autoFillPointCut()")
public void autoFill(JoinPoint joinPoint){
log.info("开始进行公共字段的自动填充");

// 获取当前被拦截的方法上的数据库操作类型
MethodSignature signature = (MethodSignature) joinPoint.getSignature(); //方法签名对象
AutoFill autoFill=signature.getMethod().getAnnotation(AutoFill.class); // 获得方法上的注解对象
OperationType operationType = autoFill.value(); // 获得数据库操作类型

// 获取到当前被拦截的方法的参数-实体对象
Object[] args = joinPoint.getArgs();
if(args==null ||args.length==0){
return;
}
Object entity=args[0];

// 准备赋值的数据
LocalDateTime now = LocalDateTime.now();
Long currentId = BaseContext.getCurrentId();

// 根据当前不同的操作类型,为对应的属性通过反射来赋值
if(operationType == OperationType.INSERT){
try{
// 为4个公共字段赋值
Method setCreateTimes = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
Method setCreateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
Method setUpdateTimes = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
setCreateTimes.invoke(entity,now);
setCreateUser.invoke(entity,currentId);
setUpdateTimes.invoke(entity,now);
setUpdateUser.invoke(entity,currentId);
}catch(Exception e){
e.printStackTrace();
}

}else if(operationType== OperationType.UPDATE){
try{
// 为2个公共字段赋值
Method setUpdateTimes = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
setUpdateTimes.invoke(entity,now);
setUpdateUser.invoke(entity,currentId);
}catch(Exception e){
e.printStackTrace();
}

}
}
}

在Mapper的方法上加入AutoFill注解

update就加上@AutoFill(OperationType.UPDATE),insert就加上@AutoFill(OperationType.INSERT)

1
2
@AutoFill(OperationType.UPDATE)
void update(Category category);

注释掉原来的service层的赋值时间和用户的代码

就类似这样
image

测试效果

我修改了一个员工,时间也自动更新了
image

新增菜品

阿里云上传图片

配置阿里云

这个首先你要有阿里云的存储OSS,这个很便宜,新账号也有免费体验,反正你就是要搞到

  1. 登录进去
    首先你先登录进去,按照图示操作
    图示
  2. 创建用户
    创建用户
  3. 创建完成之后
    你会得到AccessKeyID和AccessKeySecret,记录下来
    AccessKeyID和AccessKeySecret
  4. 创建Bucket
    记得设置成可以公开访问的,是否公开写倒没啥关系
    创建Bucket
  5. 创建完成之后
    你会得到Bucket名称,记录下来
    Bucket名称
  6. 配置你创建用户的权限
    配置你创建用户的权限

java代码部分

  1. 添加maven依赖

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
    <version>2.4.0</version>
    </dependency>
    <dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.1</version>
    </dependency>
    <dependency>
    <groupId>org.jdom</groupId>
    <artifactId>jdom</artifactId>
    <version>1.1.3</version>
    </dependency>
  2. 配置yml文件
    在yml里面加上,这里取的是dev环境的,我们还需要去dev里面配置详细信息

    1
    2
    3
    4
    5
    alioss:
    access-key-id: ${sky.alioss.access-key-id}
    access-key-secret: ${sky.alioss.access-key-secret}
    bucket-name: ${sky.alioss.bucket-name}
    endpoint: ${sky.alioss.endpoint}

    dev-yml,这里填入你自己阿里云的信息

    1
    2
    3
    4
    5
    alioss:
    access-key-id: xxxx
    access-key-secret: xxxxx
    bucket-name: codesigner-test-oss
    endpoint: oss-cn-hangzhou.aliyuncs.com
  3. 配置工具类
    配置工具类读取配置文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    package com.sky.config;

    import com.sky.properties.AliOssProperties;
    import com.sky.utils.AliOssUtil;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;

    /**
    * ClassName: OssConfiguration
    * Package: com.sky.config
    * Description: 配置类,用于创建AliOssUtil对象
    *
    * @Author codesigner
    * @Create 2024/3/26 20:53
    * @Version 1.0
    */

    @Configuration
    @Slf4j
    public class OssConfiguration {
    @Bean
    @ConditionalOnMissingBean
    public AliOssUtil aliOssUtil(AliOssProperties aliOssProperties){
    log.info("开始上传阿里云文件上传工具类:{}",aliOssProperties);
    return new AliOssUtil(
    aliOssProperties.getEndpoint(),
    aliOssProperties.getAccessKeyId(),
    aliOssProperties.getAccessKeySecret(),
    aliOssProperties.getBucketName()
    );
    }
    }
  4. 配置controller

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    package com.sky.controller.admin;

    import com.sky.result.Result;
    import com.sky.utils.AliOssUtil;
    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.PostMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.multipart.MultipartFile;

    import java.io.IOException;
    import java.util.UUID;

    /**
    * ClassName: CommonController
    * Package: com.sky.controller.admin
    * Description: 通用接口
    *
    * @Author codesigner
    * @Create 2024/3/26 20:42
    * @Version 1.0
    */

    @RestController
    @RequestMapping("/admin/common")
    @Api(tags="通用接口")
    @Slf4j
    public class CommonController {

    @Autowired
    private AliOssUtil aliOssUtil;

    /**
    * 文件上传
    * @param file
    * @return
    * */
    @PostMapping("/upload")
    @ApiOperation("文件上传")
    public Result<String> upload(MultipartFile file){
    log.info("文件上传:{}",file);
    try {
    // 原先上传的文件名
    String originalFilename = file.getOriginalFilename();
    // 截取拓展名 abcd.png
    String extension=originalFilename.substring(originalFilename.lastIndexOf("."));
    // 构造新文件名称
    String objectName= UUID.randomUUID()+extension;
    // 文件的请求路径
    String filePath = aliOssUtil.upload(file.getBytes(),objectName);
    return Result.success(filePath);
    } catch (IOException e) {
    log.error("文件上传失败:{}",e);
    }

    return Result.error(MessageConstant.UPLOAD_FAILED);
    }
  5. 配置上传方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    package com.sky.utils;

    import com.aliyun.oss.ClientException;
    import com.aliyun.oss.OSS;
    import com.aliyun.oss.OSSClientBuilder;
    import com.aliyun.oss.OSSException;
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.extern.slf4j.Slf4j;
    import java.io.ByteArrayInputStream;

    @Data
    @AllArgsConstructor
    @Slf4j
    public class AliOssUtil {

    private String endpoint;
    private String accessKeyId;
    private String accessKeySecret;
    private String bucketName;

    /**
    * 文件上传
    *
    * @param bytes
    * @param objectName
    * @return
    */
    public String upload(byte[] bytes, String objectName) {

    // 创建OSSClient实例。
    OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

    try {
    // 创建PutObject请求。
    ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(bytes));
    } catch (OSSException oe) {
    System.out.println("Caught an OSSException, which means your request made it to OSS, "
    + "but was rejected with an error response for some reason.");
    System.out.println("Error Message:" + oe.getErrorMessage());
    System.out.println("Error Code:" + oe.getErrorCode());
    System.out.println("Request ID:" + oe.getRequestId());
    System.out.println("Host ID:" + oe.getHostId());
    } catch (ClientException ce) {
    System.out.println("Caught an ClientException, which means the client encountered "
    + "a serious internal problem while trying to communicate with OSS, "
    + "such as not being able to access the network.");
    System.out.println("Error Message:" + ce.getMessage());
    } finally {
    if (ossClient != null) {
    ossClient.shutdown();
    }
    }

    //文件访问路径规则 https://BucketName.Endpoint/ObjectName
    StringBuilder stringBuilder = new StringBuilder("https://");
    stringBuilder
    .append(bucketName)
    .append(".")
    .append(endpoint)
    .append("/")
    .append(objectName);

    log.info("文件上传到:{}", stringBuilder.toString());

    return stringBuilder.toString();
    }
    }

  6. 效果

controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package com.sky.controller.admin;

import com.sky.dto.DishDTO;
import com.sky.result.Result;
import com.sky.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.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
* ClassName: DishController
* Package: com.sky.controller.admin
* Description: 菜品管理
*
* @Author codesigner
* @Create 2024/3/26 22:16
* @Version 1.0
*/
@RestController
@RequestMapping("/admin/dish")
@Api(tags="菜品相关接口")
@Slf4j
public class DishController {

@Autowired
private DishService dishService;

@PostMapping
@ApiOperation("新增菜品")
public Result save(@RequestBody DishDTO dishDTO){
log.info("新增菜品:{}",dishDTO);
dishService.saveWithFlavor(dishDTO);
return Result.success();
}
}

service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.sky.service;

import com.sky.dto.DishDTO;

/**
* ClassName: DishService
* Package: com.sky.service
* Description:
*
* @Author codesigner
* @Create 2024/3/26 22:21
* @Version 1.0
*/

public interface DishService {
/**
* 新增菜品和对应的口味
* @param dishDTO
* */
public void saveWithFlavor(DishDTO dishDTO);
}

serviceImpl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package com.sky.service.impl;

import com.sky.dto.DishDTO;
import com.sky.entity.Dish;
import com.sky.entity.DishFlavor;
import com.sky.mapper.DishFlavorMapper;
import com.sky.mapper.DishMapper;
import com.sky.service.DishService;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
* ClassName: DishServiceImpl
* Package: com.sky.service.impl
* Description:
*
* @Author codesigner
* @Create 2024/3/26 22:28
* @Version 1.0
*/
@Service
@Slf4j
public class DishServiceImpl implements DishService {

@Autowired
private DishMapper dishMapper;
@Autowired
private DishFlavorMapper dishFlavorMapper;
/**
* 新增菜品和对应的口味
* @param dishDTO
* */
@Override
@Transactional
public void saveWithFlavor(DishDTO dishDTO){
// 向菜品表插入1条数据
Dish dish=new Dish();

BeanUtils.copyProperties(dishDTO,dish);

dishMapper.insert(dish);

// 获取insert语句生成的主键值
Long dishId=dish.getId();

List<DishFlavor> flavors= dishDTO.getFlavors();
if(flavors!=null && flavors.size()>0){
flavors.forEach(dishFlavor -> {
dishFlavor.setDishId(dishId);
});
// 向口味表插入n条数据
dishFlavorMapper.insertBatch(flavors);
}

}
}

mapper

DishMapper

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package com.sky.mapper;

import com.sky.annotation.AutoFill;
import com.sky.entity.Dish;
import com.sky.entity.DishFlavor;
import com.sky.enumeration.OperationType;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

import java.util.List;

@Mapper
public interface DishMapper {

/**
* 根据分类id查询菜品数量
* @param categoryId
* @return
*/
@Select("select count(id) from dish where category_id = #{categoryId}")
Integer countByCategoryId(Long categoryId);

/**
* 插入菜品数据
* @param dish
* */
@AutoFill(OperationType.INSERT)
void insert(Dish dish);
}

DishFlavorMapper

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.sky.mapper;

import com.sky.entity.DishFlavor;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Service;

import java.util.List;

/**
* ClassName: DishFlavorMapper
* Package: com.sky.mapper
* Description:
*
* @Author codesigner
* @Create 2024/3/26 22:42
* @Version 1.0
*/
@Mapper
public interface DishFlavorMapper {
/**
* 批量插入口味数据
* @param flavors
* */

void insertBatch(List<DishFlavor> flavors);
}

xml

DishMapper.xml
这里添加了useGeneratedKeys, keyProperty这两个属性,这样可以在执行完这个sql之后将主键返回,主键值为id,这时候在实现类中的
Long dishId=dish.getId();才能够有作用

1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.sky.mapper.DishMapper">
<insert id="insert" useGeneratedKeys="true" keyProperty="id">

insert into dish (name, category_id, price, image, description, create_time, update_time, create_user, update_user,status)
values
(#{name},#{categoryId},#{price},#{image}, #{description}, #{createTime}, #{updateTime}, #{createUser}, #{updateUser},#{status})
</insert>
</mapper>

DishFlavorMapper.xml

1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.sky.mapper.DishFlavorMapper">
<insert id="insertBatch">
insert into dish_flavor (dish_id, name, value) VALUES
<foreach collection="flavors" item="df" separator=",">
(#{df.dishId},#{df.name},#{df.value})
</foreach>
</insert>
</mapper>

测试结果

成功将菜品和口味插入到数据库
image
image

分页查询菜品

controller

1
2
3
4
5
6
7
8
9
10
11
/**
* 菜品分页查询
* @param dishPageQueryDTO
* */
@GetMapping("/page")
@ApiOperation("菜品分页查询")
public Result<PageResult> page(DishPageQueryDTO dishPageQueryDTO){
log.info("菜品分页查询:{}",dishPageQueryDTO);
PageResult pageResult=dishService.pageQuery(dishPageQueryDTO);
return Result.success(pageResult);
}

service

1
2
3
4
5
/**
* 菜品分页查询
* @param dishPageQueryDTO
* */
PageResult pageQuery(DishPageQueryDTO dishPageQueryDTO);

serviceImpl

1
2
3
4
5
6
7
8
9
10
//**
* 菜品分页查询
*
* @param dishPageQueryDTO
*/
public PageResult pageQuery(DishPageQueryDTO dishPageQueryDTO) {
PageHelper.startPage(dishPageQueryDTO.getPage(), dishPageQueryDTO.getPageSize());
Page<DishVO> page = dishMapper.pageQuery(dishPageQueryDTO);
return new PageResult(page.getTotal(), page.getResult());
}

mapper

1
2
3
4
5
6
 /**
* 菜品分页查询
*
* @param dishPageQueryDTO
*/
Page<DishVO> pageQuery(DishPageQueryDTO dishPageQueryDTO);

xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<select id="pageQuery" resultType="com.sky.vo.DishVO">
select d.*,c.name as categoryName from dish d left outer join category c on d.category_id = c.id
<where>
<if test="name!=null">
and d.name like concat('%',#{name},'%')
</if>
<if test="categoryId!=null">
and d.category_id =#{categoryId}
</if>
<if test="status!=null">
and d.status =#{status}
</if>
</where>
order by d.create_time desc
</select>

删除菜品

controller

1
2
3
4
5
6
7
@DeleteMapping
@ApiOperation("菜品批量删除")
public Result delete(@RequestParam List<Long> ids){
log.info("菜品批量删除:{}",ids);
dishService.deleteBatch(ids);
return Result.success();
}

service

1
2
3
4
5
/**
* 菜品批量删除
* @param ids
* */
void deleteBatch(List<Long> ids);

serviceImpl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
 /**
* 菜品批量删除
* @param ids
* */
@Transactional
public void deleteBatch(List<Long> ids){
// 判断当前菜品是否能够删除 -- 是否存在起售中的菜品
for(Long id:ids){
Dish dish=dishMapper.getById(id);
if(dish.getStatus()== StatusConstant.ENABLE){
// 当前菜品处于起售中,不能删除
throw new DeletionNotAllowedException(MessageConstant.DISH_ON_SALE);
}
}

// 判断当前菜品是否能够删除--是否被套餐关联了??
List<Long> setmealIds=setmealDishMapper.getSetmealIdsByDishIds(ids);
if(setmealIds!=null && setmealIds.size()>0){
// 当前菜品被套餐关联了,不能删除
throw new DeletionNotAllowedException(MessageConstant.DISH_BE_RELATED_BY_SETMEAL);
}

// 删除菜品
// for (Long id : ids) {
// dishMapper.deleteById(id);
// // 删除菜品关联的口味数据
// dishFlavorMapper.deleteByDishId(id);
// }

dishFlavorMapper.deleteByDishIds(ids);
dishMapper.deleteByIds(ids);
}

DishMapper

1
2
3
4
5
6
7
8
/**
* 根据主键删除菜品
* @param id
* */
@Delete("delete from dish where id = #{id}")
void deleteById(Long id);

void deleteByIds(List<Long> ids);

DishMapperXml

1
2
3
4
5
6
<delete id="deleteByIds">
delete from dish where id in
<foreach collection="ids" separator="," open="(" close=")" item="id">
#{id}
</foreach>
</delete>

DishFlavorMapper

1
2
3
4
5
6
7
8
/**
* 根据菜品id删除口味
* @param dishId
* */
@Delete("delete from dish_flavor where dish_id=#{dishId}")
void deleteByDishId(Long dishId);

void deleteByDishIds(List<Long> dishIds);

DishFlavorMapperXml

1
2
3
4
5
6
<delete id="deleteByDishIds">
delete from dish_flavor where dish_id in
<foreach collection="dishIds" open="(" close=")" separator="," item="dishId">
#{dishId}
</foreach>
</delete>

SetmealDishMapper

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.sky.mapper;

import org.apache.ibatis.annotations.Mapper;

import java.util.List;

/**
* ClassName: SetmealDishMapper
* Package: com.sky.mapper
* Description:
*
* @Author codesigner
* @Create 2024/3/27 20:56
* @Version 1.0
*/

@Mapper
public interface SetmealDishMapper {

/**
* 根据菜品id查询对应的套餐id
* @param dishIds
* */
List<Long> getSetmealIdsByDishIds(List<Long> dishIds);

}

SetmealDishMapperXml

1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.sky.mapper.SetmealDishMapper">
<select id="getSetmealIdsByDishIds" resultType="java.lang.Long">
select setmeal_id from setmeal_dish where dish_id in
<foreach collection="dishIds" item="dishId" separator="," open="(" close=")">
#{dishId}
</foreach>
</select>
</mapper>

捕获异常

1
2
3
4
5
@ExceptionHandler
public Result exceptionHandler(DeletionNotAllowedException ex){
String message=ex.getMessage();
return Result.error(message);
}

菜品编辑

根据id查询

controller

1
2
3
4
5
6
7
8
9
10
11
/**
* 根据id查询菜品
* @param id
* */
@GetMapping("/{id}")
@ApiOperation("根据id查询菜品")
public Result<DishVO> getById(@PathVariable Long id){
log.info("根据id查询菜品:{}",id);
DishVO dishVO=dishService.getByIdWithFlavor(id);
return Result.success(dishVO);
}

service

1
2
3
4
5
/**
* 根据id查询菜品和对应口味数据
* @param id
* */
DishVO getByIdWithFlavor(Long id);

serviceImp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* 根据id查询菜品和对应口味数据
* @param id
* */
@Override
public DishVO getByIdWithFlavor(Long id) {
// 根据id查询菜品数据
Dish dish=dishMapper.getById(id);
// 根据菜品id查询口味数据
List<DishFlavor> dishFlavors=dishFlavorMapper.getByDishId(id);
// 将查询到的数据封装到VO
DishVO dishVo=new DishVO();
BeanUtils.copyProperties(dish,dishVo);
dishVo.setFlavors(dishFlavors);
return dishVo;
}

mapper

1
2
3
4
5
6
/**
* 根据菜品id查询对应的口味数据
* @param dishId
* */
@Select("select * from dish_flavor where dish_id=#{dishId}")
List<DishFlavor> getByDishId(Long dishId);

编辑

controller

1
2
3
4
5
6
7
@PutMapping
@ApiOperation("修改菜品")
public Result update(@RequestBody DishDTO dishDTO){
log.info("修改菜品:{}",dishDTO);
dishService.updateWithFlavor(dishDTO);
return Result.success();
}

service

1
2
3
4
5
/**
* 根据id修改菜品基本信息和对应的口味信息
* @param dishDTO
* */
void updateWithFlavor(DishDTO dishDTO);

serviceImp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* 根据id修改菜品基本信息和对应的口味信息
* @param dishDTO
* */
@Override
@Transactional
public void updateWithFlavor(DishDTO dishDTO) {
// 修改菜品表基本信息
Dish dish=new Dish();
BeanUtils.copyProperties(dishDTO,dish);
dishMapper.update(dish);
// 删除原有的口味数据
dishFlavorMapper.deleteByDishId(dishDTO.getId());
// 重新插入口味数据
List<DishFlavor> flavors = dishDTO.getFlavors();
if (flavors != null && flavors.size() > 0) {
flavors.forEach(dishFlavor -> {
dishFlavor.setDishId(dishDTO.getId());
});
// 向口味表插入n条数据
dishFlavorMapper.insertBatch(flavors);
}

}

mapper

1
2
3
4
5
6
/**
* 根据id动态修改菜品
* @param dish
* */
@AutoFill(value=OperationType.UPDATE)
void update(Dish dish);

xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<update id="update">
update dish
<set>
<if test="name!=null">
name=#{name},
</if>
<if test="categoryId!=null">
category_id=#{categoryId},
</if>
<if test="price!=null">
price=#{price},
</if>
<if test="image!=null">
image=#{image},
</if>
<if test="description!=null">
description=#{description},
</if>
<if test="status!=null">
status=#{status},
</if>
<if test="updateTime!=null">
update_time=#{updateTime},
</if>
<if test="updateUser!=null">
update_user=#{updateUser},
</if>
</set>
where id=#{id}
</update>

结语

本篇文章就到这里了,学java好像的确有点累,可能和我基础不扎实在这硬学有关系,不管了,硬着头皮学吧,这个学完了,我估计以后也不太可能会碰java了。债见

上一篇:
keep-alive的使用及细节
下一篇:
【Python学习】01-一篇文章帮你搞定Python基础