mybatis plus demo

master
zyx 3 years ago
parent d4a5a30c4e
commit 58ad52091f

@ -10,10 +10,14 @@
<name>${project.artifactId}</name> <name>${project.artifactId}</name>
<properties> <properties>
<java.version>1.8</java.version>
<maven.compiler.source>8</maven.compiler.source> <maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target> <maven.compiler.target>8</maven.compiler.target>
<mybatis-plus.version>3.5.1</mybatis-plus.version>
<hutool.version>5.8.9</hutool.version>
<jave-core.version>2.4.6</jave-core.version>
<jave-native-win64.version>2.4.6</jave-native-win64.version>
</properties> </properties>
<!-- <!--
Using Spring Boot without the Parent POM Using Spring Boot without the Parent POM
https://docs.spring.io/spring-boot/docs/2.6.6/maven-plugin/reference/pdf/spring-boot-maven-plugin-reference.pdf https://docs.spring.io/spring-boot/docs/2.6.6/maven-plugin/reference/pdf/spring-boot-maven-plugin-reference.pdf
@ -36,6 +40,48 @@
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId> <artifactId>spring-boot-starter-web</artifactId>
</dependency> </dependency>
<!--参数校验-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<!-- springboot2.6.5中已经引用, 对应版本为8.0.28 -->
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool.version}</version>
</dependency>
<!-- 解析视频长度 -->
<dependency>
<groupId>ws.schild</groupId>
<artifactId>jave-core</artifactId>
<version>${jave-core.version}</version>
</dependency>
<dependency>
<groupId>ws.schild</groupId>
<artifactId>jave-native-win64</artifactId>
<version>${jave-native-win64.version}</version>
</dependency>
</dependencies> </dependencies>
<build> <build>

@ -1,18 +0,0 @@
package com.zyx.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author Yaxi.Zhang
* @since 2022/10/15 07:58
*/
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello() {
return "Hello Jenkins";
}
}

@ -1,15 +1,13 @@
package com.zyx; package com.zyx.mpdemo;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author Yaxi.Zhang
* @since 2022/10/15 07:56
*/
@SpringBootApplication @SpringBootApplication
public class HelloApp { public class MpDemoApp {
public static void main(String[] args) { public static void main(String[] args) {
SpringApplication.run(HelloApp.class, args); SpringApplication.run(MpDemoApp.class, args);
} }
} }

@ -0,0 +1,42 @@
package com.zyx.mpdemo.common.constant;
/**
* @author Yaxi.Zhang
* @since 2022/10/1 08:19
*/
public class ResponseCode {
// ==================================== HTPP状态码开始 ====================================
/** 200成功 服务器已成功处理了请求*/
public static final int RESPONSE_CODE_200 = 200;
/** 201 服务响应码--失败 */
public static final int RESPONSE_CODE_201 = 201;
/** 202已接受,但未处理) 服务器已接受请求,但尚未处理 */
public static final int RESPONSE_CODE_202 = 202;
/** 204无内容 服务器成功处理了请求,但没有返回任何内容。 */
public static final int RESPONSE_CODE_204 = 204;
/** 206 GET FlashGet
* HTTP 使 */
public static final int RESPONSE_CODE_206 = 206;
/** (语法错误请求) 服务器不理解请求的语法。 1、语义有误当前请求无法被服务器理解。除非进行修改否则客户端不应该重复提交这个请求。2、请求参数有误。 */
public static final int RESPONSE_CODE_400 = 400;
/** 401未授权 请求要求身份验证。 对于需要登录的网页,服务器可能返回此响应。 */
public static final int RESPONSE_CODE_401 = 401;
/** 403禁止 服务器拒绝请求。服务器理解客户的请求,但拒绝处理它。通常由于服务器上文件或目录的权限设置导致。 */
public static final int RESPONSE_CODE_403 = 403;
/** 404未找到 服务器找不到请求的网页。 例如,对于服务器上不存在的网页经常会返回此代码。 */
public static final int RESPONSE_CODE_404 = 404;
/** 408请求超时 在服务器许可的等待时间内,客户一直没有发出任何请求。客户可以在以后重复同一请求。 */
public static final int RESPONSE_CODE_408 = 408;
/** 411需要有效长度 服务器不能处理请求除非客户发送一个Content-Length头。 */
public static final int RESPONSE_CODE_411 = 411;
/** 414请求的 URI 过长) 请求的 URI通常为网址过长服务器无法处理。 */
public static final int RESPONSE_CODE_414 = 414;
/** 415不支持的媒体类型 请求的格式不受请求页面的支持。 */
public static final int RESPONSE_CODE_415 = 415;
/** 416请求范围不符合要求 如果页面无法提供请求的范围,则服务器会返回此状态代码。 */
public static final int RESPONSE_CODE_416 = 416;
/** 500 内部应用程序错误 */
public static final int RESPONSE_CODE_500 = 500;
// ==================================== HTPP状态码结束 ====================================
}

@ -0,0 +1,21 @@
package com.zyx.mpdemo.common.exception;
import com.zyx.mpdemo.common.constant.ResponseCode;
import com.zyx.mpdemo.common.exception.base.BaseException;
/**
* @author Yaxi.Zhang
* @since 2022/10/1 08:17
*/
public class BusinessException extends BaseException {
public BusinessException(String message) {
super(message);
}
public BusinessException() {
super(ResponseCode.RESPONSE_CODE_500, "内部系统错误");
}
}

@ -0,0 +1,47 @@
package com.zyx.mpdemo.common.exception.base;
import com.zyx.mpdemo.common.constant.ResponseCode;
/**
* <p>
*
* @author Yaxi.Zhang
* @since 2022/10/1 08:13
*/
public abstract class BaseException extends RuntimeException {
private int code = ResponseCode.RESPONSE_CODE_200;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public BaseException(int code, String message) {
super(message);
this.code = code;
}
public BaseException(String message) {
super(message);
}
public BaseException(String message, Throwable cause) {
super(message, cause);
}
public BaseException(Throwable cause) {
super(cause);
}
public BaseException(String message, Throwable cause,
boolean enableSuppression,
boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}

@ -0,0 +1,14 @@
package com.zyx.mpdemo.common.exception.code;
/**
* <p>Response
*
* @author Yaxi.Zhang
* @since 2022/10/7 15:35
*/
public interface IErrorCode {
Integer getCode();
String getMessage();
}

@ -0,0 +1,46 @@
package com.zyx.mpdemo.common.exception.code;
import lombok.AllArgsConstructor;
import org.springframework.http.HttpStatus;
/**
* Response
*/
@AllArgsConstructor
public enum ResultCode implements IErrorCode {
SUCCESS(HttpStatus.OK.value(), "操作成功!"),
FAILED(HttpStatus.INTERNAL_SERVER_ERROR.value(), "操作失败!"),
AUTHENTICATION_FAILED(50001, "获取token失败!"),
AUTH_SERVER_ERROR(50002, "授权服务异常!"),
LOGIN_METHOD_IS_EMPTY(50003, "登录方式不能为空!"),
LOGIN_METHOD_IS_INVALID(50004, "登录方式只支持password模式!"),
UNAUTHORIZED(40001, "身份认证失败!"),
VALIDATE_FAILED(40002, "Token参数校验失败,请检查Token是否正确!"),
FORBIDDEN(40003, "无权限请求,请检测当前用户身份信息!"),
ACCOUNT_IS_EMPTY(40004, "账号不能为空!"),
PASSWORD_IS_EMPTY(40005, "密码不能为空!");
/**
*
*/
private final Integer code;
/**
*
*/
private final String message;
@Override
public Integer getCode() {
return code;
}
@Override
public String getMessage() {
return message;
}
}

@ -0,0 +1,128 @@
package com.zyx.mpdemo.common.resp;
import com.zyx.mpdemo.common.exception.code.IErrorCode;
import com.zyx.mpdemo.common.exception.code.ResultCode;
import com.zyx.mpdemo.common.resp.base.BaseResponse;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* @author Yaxi.Zhang
* @since 2022/10/1 08:32
*/
@EqualsAndHashCode(callSuper = true)
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CommonResponse<T> extends BaseResponse implements Serializable {
private T data;
public CommonResponse(Integer code, String message) {
this(code, message, null);
}
public CommonResponse(Integer code, String message, T data) {
this.code = code;
this.message = message;
this.data = data;
}
/**
*
*/
public static <T> CommonResponse<T> success(T data) {
return new CommonResponse<>(ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMessage(), data);
}
/**
*
*/
public static <T> CommonResponse<T> success(T data, String message) {
return new CommonResponse<>(ResultCode.SUCCESS.getCode(), message, data);
}
/**
*
*/
public static <T> CommonResponse<T> failed(IErrorCode errorCode) {
return new CommonResponse<>(errorCode.getCode(), errorCode.getMessage(), null);
}
/**
*
*/
public static <T> CommonResponse<T> failed(IErrorCode errorCode, String message) {
return new CommonResponse<>(errorCode.getCode(), message, null);
}
/**
*
*/
public static <T> CommonResponse<T> failed(String message) {
return new CommonResponse<>(ResultCode.FAILED.getCode(), message, null);
}
/**
*
*/
public static <T> CommonResponse<T> failed(Integer code, String message) {
return new CommonResponse<>(code, message, null);
}
/**
*
*/
public static <T> CommonResponse<T> failed() {
return failed(ResultCode.FAILED);
}
/**
*
*/
public static <T> CommonResponse<T> validateFailed() {
return failed(ResultCode.VALIDATE_FAILED);
}
/**
*
*/
public static <T> CommonResponse<T> validateFailed(String message) {
return new CommonResponse<>(ResultCode.VALIDATE_FAILED.getCode(),
String.format("%s,%s", message, ResultCode.VALIDATE_FAILED.getMessage()), null);
}
/**
*
*/
public static <T> CommonResponse<T> authenticationFailed(String message) {
return new CommonResponse<T>(ResultCode.AUTHENTICATION_FAILED.getCode(),
String.format("%s,%s", message, ResultCode.AUTHENTICATION_FAILED.getMessage()), null);
}
/**
* Token
*/
public static <T> CommonResponse<T> authenticationExpired(String message) {
return new CommonResponse<>(ResultCode.UNAUTHORIZED.getCode(), String.format("%s,%s", message, ResultCode.UNAUTHORIZED.getMessage()), null);
}
/**
* Token
*/
public static <T> CommonResponse<T> unauthorized(T data) {
return new CommonResponse<>(ResultCode.UNAUTHORIZED.getCode(), ResultCode.UNAUTHORIZED.getMessage(), data);
}
/**
*
*/
public static <T> CommonResponse<T> forbidden(T data) {
return new CommonResponse<>(ResultCode.FORBIDDEN.getCode(), ResultCode.FORBIDDEN.getMessage(), data);
}
}

@ -0,0 +1,25 @@
package com.zyx.mpdemo.common.resp.base;
import com.zyx.mpdemo.common.constant.ResponseCode;
import lombok.Data;
/**
* @author Yaxi.Zhang
* @since 2022/10/1 08:32
*/
@Data
public class BaseResponse {
protected int code = ResponseCode.RESPONSE_CODE_200;
protected String message;
public BaseResponse() {
}
public BaseResponse(int status, String message) {
this.code = status;
this.message = message;
}
}

@ -0,0 +1,39 @@
package com.zyx.mpdemo.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.zyx.mpdemo.helpers.injector.EasySqlInjector;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author Yaxi.Zhang
* @since 2022/3/29 10:56
*/
@Configuration
// 扫描mapper接口所在的包可以从启动类移动到该配置类
@MapperScan("com.zyx.mpdemo.mapper")
public class MyBatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 添加分页插件
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
// 添加乐观锁插件
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
/**
* EasySqlInjector
* mybatis-plus使InsertBatchSomeColumn
*/
@Bean
public EasySqlInjector sqlInjector() {
return new EasySqlInjector();
}
}

@ -0,0 +1,41 @@
package com.zyx.mpdemo.config;
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.util.Calendar;
import java.util.Date;
/**
* <p>MyBatisPlus
*
* @author Yaxi.Zhang
* @since 2022/11/21 10:27
*/
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
// log.info("start insert fill ....");
this.strictInsertFill(metaObject, "createTime", Date.class, Calendar.getInstance().getTime()); // 起始版本 3.3.0(推荐使用)
this.strictInsertFill(metaObject, "updateTime", Date.class, Calendar.getInstance().getTime()); // 起始版本 3.3.0(推荐使用)
// 或者
// this.strictInsertFill(metaObject, "createTime", () -> Calendar.getInstance().getTime(), Date.class); // 起始版本 3.3.3(推荐)
// 或者
// this.fillStrategy(metaObject, "createTime", Calendar.getInstance().getTime()); // 也可以使用(3.3.0 该方法有bug)
}
@Override
public void updateFill(MetaObject metaObject) {
// log.info("start update fill ....");
this.strictUpdateFill(metaObject, "updateTime", Date.class, Calendar.getInstance().getTime()); // 起始版本 3.3.0(推荐)
// 或者
// this.strictUpdateFill(metaObject, "updateTime", () -> Calendar.getInstance().getTime(), Date.class); // 起始版本 3.3.3(推荐)
// 或者
// this.fillStrategy(metaObject, "updateTime", Calendar.getInstance().getTime()); // 也可以使用(3.3.0 该方法有bug)
}
}

@ -0,0 +1,25 @@
package com.zyx.mpdemo.config;
import org.apache.ibatis.reflection.wrapper.ObjectWrapperFactory;
import org.springframework.boot.context.properties.ConfigurationPropertiesBinding;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
/**
* @author Yaxi.Zhang
* @since 2022/3/28 18:09
* reference: https://www.cxyzjd.com/article/qq_39720208/104631573
*/
@Component
@ConfigurationPropertiesBinding
public class ObjectWrapperFactoryConverter implements Converter<String,ObjectWrapperFactory> {
@Override
public ObjectWrapperFactory convert(String source) {
try {
return (ObjectWrapperFactory) Class.forName(source).newInstance();
} catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
}

@ -0,0 +1,69 @@
package com.zyx.mpdemo.controller;
import com.zyx.mpdemo.common.resp.CommonResponse;
import com.zyx.mpdemo.model.req.BatchLearnedReq;
import com.zyx.mpdemo.model.req.CourseDetailReq;
import com.zyx.mpdemo.model.req.CourseListReq;
import com.zyx.mpdemo.model.vo.CourseDetailVO;
import com.zyx.mpdemo.model.vo.CourseInfoVO;
import com.zyx.mpdemo.model.vo.CourseListVO;
import com.zyx.mpdemo.service.ICourseService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
/**
*
*
* @author Yaxi.Zhang
* @since 2023/1/26 08:52
*/
@Slf4j
@Controller
@ResponseBody
@RequestMapping("/course")
public class CourseController {
@Resource
private ICourseService courseService;
/**
*
*
* @return
*/
@GetMapping("/course-infos")
public CommonResponse<List<CourseInfoVO>> getCourseInfo() {
return CommonResponse.success(courseService.getCourseInfo(), "查询所有课程名称以及章节号成功");
}
/**
* id
*/
@PostMapping("/course-list")
public CommonResponse<CourseListVO> getCourseList(@Validated @RequestBody CourseListReq courseListReq) {
return CommonResponse.success(courseService.getCourseList(courseListReq), "查询课程列表成功");
}
/**
*
*/
@PostMapping("/course-detail")
public CommonResponse<List<CourseDetailVO>> getCourseDetail(@Validated @RequestBody CourseDetailReq courseDetailReq) {
return CommonResponse.success(courseService.getCourseDetail(courseDetailReq), "查询课程详情成功");
}
/**
*
*/
@PutMapping("/batch-learned")
public CommonResponse<Void> batchLearned(@Validated @RequestBody BatchLearnedReq batchLearnedReq) {
courseService.batchLearned(batchLearnedReq);
return CommonResponse.success(null, "批量修改课程为已学完成功");
}
}

@ -0,0 +1,64 @@
package com.zyx.mpdemo.helpers.handler;
import cn.hutool.core.collection.CollUtil;
import com.zyx.mpdemo.common.constant.ResponseCode;
import com.zyx.mpdemo.common.exception.BusinessException;
import com.zyx.mpdemo.common.exception.code.ResultCode;
import com.zyx.mpdemo.common.resp.CommonResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import java.lang.reflect.Executable;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* <p>
*
* @author Yaxi.Zhang
* @since 2022/10/1 08:27
*/
@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {
@ResponseBody
@ExceptionHandler(value = Exception.class)
public CommonResponse<Void> invalidCommon(Exception ex) {
log.error("全局异常捕获", ex);
return new CommonResponse<>(ResponseCode.RESPONSE_CODE_500, "全局异常捕获:" + ex.getMessage(), null);
}
@ResponseBody
@ExceptionHandler(value = BusinessException.class)
public CommonResponse<Void> invalidBusiness(BusinessException ex) {
log.error("业务异常捕获", ex);
return new CommonResponse<>(ex.getCode(), ex.getMessage(), null);
}
@ResponseBody
@ExceptionHandler(value = MethodArgumentNotValidException.class)
public CommonResponse<Void> methodArgumentNotValidException(MethodArgumentNotValidException ex) {
log.error("全局异常捕获", ex);
List<ObjectError> allErrors = ex.getBindingResult().getAllErrors();
String errorStr = "";
if (CollUtil.isNotEmpty(allErrors)) {
errorStr = allErrors.stream().map(ObjectError::getDefaultMessage).collect(Collectors.joining(","));
}
Executable executable = ex.getParameter().getParameter().getDeclaringExecutable();
if (Objects.nonNull(executable)) {
String clazz = executable.getDeclaringClass().getName();
String method = executable.getName();
log.error("{}#{} 参数校验失败: [{}]", clazz, method, errorStr);
}
return new CommonResponse<>(ResultCode.FAILED.getCode(), "参数校验失败:" + errorStr, null);
}
}

@ -0,0 +1,25 @@
package com.zyx.mpdemo.helpers.injector;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.extension.injector.methods.InsertBatchSomeColumn;
import java.util.List;
/**
* <p>mybatis-plusSQL
*
* @author Yaxi.Zhang
* @since 2022/12/7 10:40
*/
public class EasySqlInjector extends DefaultSqlInjector {
@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
// 注意:此SQL注入器继承了DefaultSqlInjector(默认注入器)
// 调用了DefaultSqlInjector的getMethodList方法,保留了mybatis-plus的自带方法
List<AbstractMethod> methodList = super.getMethodList(mapperClass, tableInfo);
methodList.add(new InsertBatchSomeColumn());
return methodList;
}
}

@ -0,0 +1,31 @@
package com.zyx.mpdemo.helpers.utils;
import com.zyx.mpdemo.model.entity.Course;
import com.zyx.mpdemo.model.vo.CourseCost;
import java.util.List;
import java.util.stream.Collectors;
/**
* <p>
*
* @author Yaxi.Zhang
* @since 2022/11/21 14:23
*/
public class CourseStatisticsUtils {
/**
*
*/
public static CourseCost getCourseCost(List<Course> courses) {
List<CourseCost> courseCostList = courses.stream()
.map(it -> new CourseCost().setHours(it.getCourseHours()).setMinutes(it.getCourseMinutes()).setSeconds(it.getCourseSeconds()))
.collect(Collectors.toList());
return CourseCost.fromList(courseCostList);
}
public static double getLearnedPercentage(CourseCost learnedCourse, CourseCost allCourse) {
return learnedCourse.getCourseSeconds() * 1.0 / allCourse.getCourseSeconds();
}
}

@ -0,0 +1,160 @@
package com.zyx.mpdemo.helpers.utils;
import com.zyx.mpdemo.model.entity.Product;
import javax.xml.bind.annotation.XmlElement;
import java.io.*;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
/**
* @author Yaxi.Zhang
* @since 2022/9/2 16:58
*/
public class GenerateSqlFromEntityUtil {
public static void main(String[] a) {
// 实体类的位置
Class klass = Product.class;
// 生成的sql语句的位置
String outputPath = "D:/outSql/Product.txt";
generateTableSql(klass, outputPath, null);
System.out.println("生成结束");
}
public static void writeFile(String content, String outputPath) {
File file = new File(outputPath);
System.out.println("文件路径: " + file.getAbsolutePath());
// 输出文件的路径
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
FileOutputStream fos = null;
OutputStreamWriter osw = null;
BufferedWriter out = null;
try {
// 如果文件存在,就删除
if (file.exists()) {
file.delete();
}
file.createNewFile();
fos = new FileOutputStream(file, true);
osw = new OutputStreamWriter(fos);
out = new BufferedWriter(osw);
out.write(content);
// 清空缓冲流,把缓冲流里的文本数据写入到目标文件里
out.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
osw.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void generateTableSql(Class obj, String outputPath, String tableName) {
// tableName 如果是 null就用类名做表名
if (tableName == null || tableName.equals("")) {
tableName = obj.getName();
tableName = tableName.substring(tableName.lastIndexOf(".") + 1);
}
// 表名用大写字母
tableName = tableName.toUpperCase();
Field[] fields = obj.getDeclaredFields();
Object param;
String column;
StringBuilder sb = new StringBuilder();
sb.append("drop table if exists ").append(tableName).append(";\r\n");
sb.append("\r\n");
sb.append("create table ").append(tableName).append("(\r\n");
System.out.println(tableName);
boolean firstId = true;
for (int i = 0; i < fields.length; i++) {
Field f = fields[i];
column = f.getName();
System.out.println(column + ", " + f.getType().getSimpleName());
param = f.getType();
sb.append(column); // 一般第一个是主键
if (param instanceof Integer) {
sb.append(" INTEGER ");
} else {
// 注意:根据需要,自行修改 varchar 的长度。这里设定为长度等于 50
int length = 50;
sb.append(" VARCHAR(" + length + ")");
}
if (firstId == true) {
sb.append(" PRIMARY KEY ");
firstId = false;
}
// 获取字段中包含 fieldMeta 的注解
// 获取属性的所有注释
Annotation[] allAnnotations = f.getAnnotations();
XmlElement xmlElement = null;
Class annotationType = null;
for (Annotation an : allAnnotations) {
sb.append(" COMMIT '");
xmlElement = (XmlElement) an;
annotationType = an.annotationType();
param = ((XmlElement) an).name();
System.out.println("属性 " + f.getName() + " ----- 的注释类型有: " + param);
sb.append(param).append("'");
}
if (i != fields.length - 1) {
// 最后一个属性后面不加逗号
sb.append(", ");
}
sb.append("\n");
}
String sql = sb.toString();
sql = sb.substring(0, sql.length() - 1) + "\n) " + "ENGINE = INNODB DEFAULT CHARSET = utf8;";
writeFile(sql, outputPath);
}
}

@ -0,0 +1,20 @@
package com.zyx.mpdemo.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zyx.mpdemo.model.entity.Course;
import org.apache.ibatis.annotations.Mapper;
/**
* <p>t_courseMapper
*
* @author zhangyaxi
* @since 2022-11-21 12:12
*/
@Mapper
public interface CourseMapper extends BaseMapper<Course> {
}

@ -0,0 +1,15 @@
package com.zyx.mpdemo.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zyx.mpdemo.model.entity.Product;
import org.springframework.stereotype.Repository;
/**
* Date:2022/2/15
* Author:ybc
* Description:
*/
@Repository
public interface ProductMapper extends BaseMapper<Product> {
}

@ -0,0 +1,49 @@
package com.zyx.mpdemo.mapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zyx.mpdemo.mapper.base.EasyBaseMapper;
import com.zyx.mpdemo.model.entity.User;
import com.zyx.mpdemo.model.vo.PartUser;
import org.apache.ibatis.annotations.MapKey;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Map;
/**
* @author Yaxi.Zhang
* @since 2022/3/28 10:25
* desc:
*/
@Repository
public interface UserMapper extends EasyBaseMapper<User> {
/**
* idmap
* , 使@Param
* , mapper.xml使#{param1} #{param2} ... , 使@Paramname
*/
@MapKey(value = "id")
Map<Long, Map<String, Object>> selectMapByAge(Integer age);
/**
*
* MyBatis-Plus
*/
Page<User> selectPageVo(@Param("page") Page<User> page, @Param("age") Integer age);
/** 注解方式查询 */
@Select("select user_name,age,email from t_user where id = #{id}")
PartUser queryPartUserById(@Param("id") Long id);
@Select("select user_name,age,email from t_user where user_name like '%${name}%'")
List<PartUser> queryPartUserLikeName(@Param("name") String name);
/** 注意${} 与 #{} 的区别 */
@Select("select user_name,age,email from t_user where user_name like '%${likeName}%'")
Page<PartUser> selectPagePartUser(@Param("page") Page<PartUser> page, @Param("likeName") String likeName);
}

@ -0,0 +1,21 @@
package com.zyx.mpdemo.mapper.base;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import java.util.Collection;
/**
* <p>EasyBaseMapper,insertBatchSomeColumn
*
* @author Yaxi.Zhang
* @since 2022/12/7 10:45
*/
public interface EasyBaseMapper<T> extends BaseMapper<T> {
/**
* mysql
*
* @param entityList
* @return
*/
Integer insertBatchSomeColumn(Collection<T> entityList);
}

@ -0,0 +1,96 @@
package com.zyx.mpdemo.model.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.zyx.mpdemo.model.enums.CourseStatusEnums;
import com.zyx.mpdemo.model.vo.CourseVO;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* <p>t_course
*
* @author Yaxi.Zhang
* @since 2022/11/21 12:13
*/
@TableName(value ="t_course")
@Data
public class Course implements Serializable {
@TableField(exist = false)
private static final long serialVersionUID = 1L;
/**
* ID
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* id
*/
private Long courseId;
/**
*
*/
private String courseName;
/**
*
*/
private String chapter;
/**
*
*/
private String sequence;
/**
*
*/
private Integer courseHours;
/**
*
*/
private Integer courseMinutes;
/**
*
*/
private Integer courseSeconds;
/**
*
*/
private CourseStatusEnums courseStatus;
/**
*
*/
@TableField(fill = FieldFill.INSERT)
private Date createTime;
/**
*
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
public CourseVO toCourseVO() {
CourseVO courseVO = new CourseVO();
courseVO.setId(this.id);
courseVO.setCourseId(this.courseId);
courseVO.setCourseName(this.courseName);
courseVO.setChapter(this.chapter);
courseVO.setSequence(this.sequence);
courseVO.setCourseHours(this.courseHours);
courseVO.setCourseMinutes(this.courseMinutes);
courseVO.setCourseSeconds(this.courseSeconds);
courseVO.setCourseStatus(this.courseStatus.getDesc());
return courseVO;
}
}

@ -0,0 +1,20 @@
package com.zyx.mpdemo.model.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.Version;
import lombok.Data;
/**
* @author Yaxi.Zhang
* @since 2022/3/29 14:06
*/
@Data
@TableName("t_product")
public class Product {
private Long id;
private String name;
private Integer price;
/** 标识乐观锁版本号字段 */
@Version
private Integer version;
}

@ -0,0 +1,37 @@
package com.zyx.mpdemo.model.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* @author Yaxi.Zhang
* @since 2022/3/28 10:03
*/
@Data
@Accessors(chain = true)
@TableName("t_user")
public class User {
// 将属性所对应的字段指定为主键
// @TableId注解的value属性用于指定主键的字段
// @TableId注解的type属性设置主键生成策略
// @TableId(value = "uid", type = IdType.AUTO)
@TableId(value = "id", type = IdType.AUTO)
private Long id;
// 指定属性所对应的字段名
// @TableField("user_name")
private String name;
private Integer age;
private String email;
// private SexEnum sex;
// @TableLogic
// private Integer isDeleted;
}

@ -0,0 +1,36 @@
package com.zyx.mpdemo.model.enums;
import com.baomidou.mybatisplus.annotation.EnumValue;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Objects;
import java.util.stream.Stream;
/**
* <p>
*
* @author Yaxi.Zhang
* @since 2022/11/21 11:36
*/
@Getter
@AllArgsConstructor
public enum CourseStatusEnums {
DELETE(0, "删除"),
LEARNING(1, "未学习"),
LEARNED(2, "已学习"),
;
@EnumValue
private final Integer code;
private final String desc;
public static CourseStatusEnums of(Integer code) {
Objects.requireNonNull(code);
return Stream.of(values())
.filter(it -> it.getCode().equals(code))
.findAny()
.orElseThrow(() -> new IllegalArgumentException(code + " not exists"));
}
}

@ -0,0 +1,35 @@
package com.zyx.mpdemo.model.enums;
import com.baomidou.mybatisplus.annotation.EnumValue;
import lombok.Getter;
import java.util.stream.Stream;
/**
* @author Yaxi.Zhang
* @since 2022/3/28 10:12
*/
@Getter
public enum SexEnum {
/** 性别 */
MALE(1, "男"),
FEMALE(2, "女");
/**
*
* : type-enums-package ,
*/
@EnumValue
private final Integer sex;
private final String sexName;
SexEnum(Integer sex, String sexName) {
this.sex = sex;
this.sexName = sexName;
}
public static SexEnum getSexEnumByCode(Integer sex) {
return Stream.of(values()).filter(item -> item.sex.equals(sex)).findFirst().orElse(null);
}
}

@ -0,0 +1,26 @@
package com.zyx.mpdemo.model.req;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* @author Yaxi.Zhang
* @since 2023/1/26 10:33
*/
@Data
public class BatchLearnedReq {
@NotNull(message = "课程名称不能为空")
private String courseName;
@NotNull(message = "章节不能为空")
private String chapter;
@NotNull(message = "开始序号不能为空")
private String startSeq;
@NotNull(message = "结束序号不能为空")
private String endSeq;
}

@ -0,0 +1,28 @@
package com.zyx.mpdemo.model.req;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.util.Set;
/**
* @author Yaxi.Zhang
* @since 2023/1/26 10:01
*/
@Data
public class CourseDetailReq {
@NotNull(message = "课程名称不能为空")
private String courseName;
/**
*
*/
private boolean needChapter = false;
/**
*
*/
private Set<String> chapters;
}

@ -0,0 +1,21 @@
package com.zyx.mpdemo.model.req;
import lombok.Data;
import javax.validation.constraints.NotNull;
/**
* @author Yaxi.Zhang
* @since 2023/1/26 13:05
*/
@Data
public class CourseListReq {
@NotNull(message = "课程id不能为空")
private Long courseId;
private Integer status;
private String chapter;
}

@ -0,0 +1,66 @@
package com.zyx.mpdemo.model.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.util.List;
/**
* <p>
*
* @author Yaxi.Zhang
* @since 2022/11/21 14:20
*/
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class CourseCost {
/** 小时数 */
private Integer hours;
/** 分钟数 */
private Integer minutes;
/** 秒数 */
private Integer seconds;
/** 获取课程秒数 */
public Integer getCourseSeconds() {
return this.hours * 60 * 60 + this.minutes * 60 + this.seconds;
}
/** 通过总的小时数、分钟数以及秒数获取实际课程耗时 */
public static CourseCost fromAll(Integer allHours, Integer allMinutes, Integer allSeconds) {
allMinutes += allSeconds / 60;
allSeconds = allSeconds % 60;
allHours += allMinutes / 60;
allMinutes = allMinutes % 60;
return new CourseCost().setHours(allHours).setMinutes(allMinutes).setSeconds(allSeconds);
}
/** 通过课程耗时列表获取实际课程耗时 */
public static CourseCost fromList(List<CourseCost> courseCostList) {
Integer hours = 0;
Integer minutes = 0;
Integer seconds = 0;
for (CourseCost courseCost : courseCostList) {
hours += courseCost.getHours();
minutes += courseCost.getMinutes();
seconds += courseCost.getSeconds();
}
return fromAll(hours, minutes, seconds);
}
/** 通过总秒数获取CourseCost */
public static CourseCost secondToCourseCost(int seconds) {
int hour = seconds / 3600;
int other = seconds % 3600;
int minute = other / 60;
int second = other % 60;
return new CourseCost().setHours(hour).setMinutes(minute).setSeconds(second);
}
}

@ -0,0 +1,70 @@
package com.zyx.mpdemo.model.vo;
import com.zyx.mpdemo.helpers.utils.CourseStatisticsUtils;
import com.zyx.mpdemo.model.entity.Course;
import com.zyx.mpdemo.model.enums.CourseStatusEnums;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.*;
import java.util.stream.Collectors;
/**
*
*
* @author Yaxi.Zhang
* @since 2023/1/26 10:02
*/
@Data
@Accessors(chain = true)
public class CourseDetailVO {
private String courseName;
private String chapter;
private CourseCost allCost;
private CourseCost learnedCost;
private CourseCost learningCost;
private String learnedPercentage;
public static CourseDetailVO getCourseDetail(String courseName, String chapter, List<Course> courses) {
List<Course> learned = courses.stream()
.filter(it -> Objects.equals(it.getCourseStatus(), CourseStatusEnums.LEARNED)).collect(Collectors.toList());
List<Course> learning = courses.stream()
.filter(it -> Objects.equals(it.getCourseStatus(), CourseStatusEnums.LEARNING)).collect(Collectors.toList());
CourseCost allCost = CourseStatisticsUtils.getCourseCost(courses);
CourseCost learnedCost = CourseStatisticsUtils.getCourseCost(learned);
CourseCost learningCost = CourseStatisticsUtils.getCourseCost(learning);
double learnedPercentageDouble = CourseStatisticsUtils.getLearnedPercentage(learnedCost, allCost);
String learnedPercentage = String.format("%.2f%%", learnedPercentageDouble * 100);
return new CourseDetailVO()
.setCourseName(courseName)
.setChapter(chapter)
.setAllCost(allCost)
.setLearnedCost(learnedCost)
.setLearningCost(learningCost)
.setLearnedPercentage(learnedPercentage);
}
public static List<CourseDetailVO> getCourseDetails(String courseName, List<Course> allCourses) {
List<CourseDetailVO> courseDetails = new ArrayList<>();
Map<String, List<Course>> courseMap = new HashMap<>();
List<String> chapters = new ArrayList<>();
allCourses.forEach(course->{
String chapter = course.getChapter();
if (!chapters.contains(chapter)) {
chapters.add(course.getChapter());
List<Course> courseList = new ArrayList<>();
courseList.add(course);
courseMap.put(chapter, courseList);
} else {
courseMap.get(chapter).add(course);
}
});
for (String chapter : chapters) {
List<Course> courses = courseMap.get(chapter);
courseDetails.add(getCourseDetail(courseName, chapter, courses));
}
return courseDetails;
}
}

@ -0,0 +1,33 @@
package com.zyx.mpdemo.model.vo;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.Set;
/**
*
*
* @author Yaxi.Zhang
* @since 2023/1/26 09:18
*/
@Data
@Accessors(chain = true)
public class CourseInfoVO {
/**
* id
*/
private Long courseId;
/**
*
*/
private String courseName;
/**
*
*/
private Set<String> chapters;
}

@ -0,0 +1,24 @@
package com.zyx.mpdemo.model.vo;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.List;
import java.util.Map;
/**
* @author Yaxi.Zhang
* @since 2023/1/26 10:56
*/
@Data
@Accessors(chain = true)
public class CourseListVO {
private Long courseId;
private String courseName;
/**
* (, )
*/
private Map<String, List<CourseVO>> courseMap;
}

@ -0,0 +1,59 @@
package com.zyx.mpdemo.model.vo;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* @author Yaxi.Zhang
* @since 2023/1/26 10:51
*/
@Data
@Accessors(chain = true)
public class CourseVO {
/**
* ID
*/
private Long id;
/**
* id
*/
private Long courseId;
/**
*
*/
private String courseName;
/**
*
*/
private String chapter;
/**
*
*/
private String sequence;
/**
*
*/
private Integer courseHours;
/**
*
*/
private Integer courseMinutes;
/**
*
*/
private Integer courseSeconds;
/**
*
*/
private String courseStatus;
}

@ -0,0 +1,14 @@
package com.zyx.mpdemo.model.vo;
import lombok.Data;
/**
* @author Yaxi.Zhang
* @since 2022/3/29 09:46
*/
@Data
public class PartUser {
private String userName;
private Integer age;
private String email;
}

@ -0,0 +1,41 @@
package com.zyx.mpdemo.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.zyx.mpdemo.model.entity.Course;
import com.zyx.mpdemo.model.req.BatchLearnedReq;
import com.zyx.mpdemo.model.req.CourseDetailReq;
import com.zyx.mpdemo.model.req.CourseListReq;
import com.zyx.mpdemo.model.vo.CourseDetailVO;
import com.zyx.mpdemo.model.vo.CourseInfoVO;
import com.zyx.mpdemo.model.vo.CourseListVO;
import java.util.List;
/**
* <p>t_courseService</p>
*
* @author zhangyaxi
* @since 2022-11-21 12:12
*/
public interface ICourseService extends IService<Course> {
/**
*
*/
List<CourseInfoVO> getCourseInfo();
/**
*
*/
List<CourseDetailVO> getCourseDetail(CourseDetailReq courseDetailReq);
/**
*
*/
void batchLearned(BatchLearnedReq batchLearnedReq);
/**
* id
*/
CourseListVO getCourseList(CourseListReq courseListReq);
}

@ -0,0 +1,11 @@
package com.zyx.mpdemo.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.zyx.mpdemo.model.entity.User;
/**
* @author Yaxi.Zhang
* @since 2022/3/28 17:09
*/
public interface IUserService extends IService<User> {
}

@ -0,0 +1,129 @@
package com.zyx.mpdemo.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zyx.mpdemo.common.exception.BusinessException;
import com.zyx.mpdemo.mapper.CourseMapper;
import com.zyx.mpdemo.model.entity.Course;
import com.zyx.mpdemo.model.enums.CourseStatusEnums;
import com.zyx.mpdemo.model.req.BatchLearnedReq;
import com.zyx.mpdemo.model.req.CourseDetailReq;
import com.zyx.mpdemo.model.req.CourseListReq;
import com.zyx.mpdemo.model.vo.CourseDetailVO;
import com.zyx.mpdemo.model.vo.CourseInfoVO;
import com.zyx.mpdemo.model.vo.CourseListVO;
import com.zyx.mpdemo.model.vo.CourseVO;
import com.zyx.mpdemo.service.ICourseService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.stream.Collectors;
/**
* <p>t_courseService</p>
*
* @author zhangyaxi
* @since 2022-11-21 12:12
*/
@Service
public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course> implements ICourseService {
@Override
public List<CourseInfoVO> getCourseInfo() {
List<CourseInfoVO> courseInfos = new ArrayList<>();
QueryWrapper<Course> queryWrapper = new QueryWrapper<>();
queryWrapper.select("distinct course_id, course_name, chapter")
.ne("course_status", CourseStatusEnums.DELETE);
List<Course> courses = list(queryWrapper);
Map<Long, List<Course>> courseMap = courses.stream().collect(Collectors.groupingBy(Course::getCourseId));
List<Long> courseIds = new ArrayList<>(courseMap.keySet());
courseIds.sort(Long::compareTo);
for (Long courseId : courseIds) {
List<Course> coursesById = courseMap.get(courseId);
if (CollUtil.isNotEmpty(coursesById)) {
String courseName = coursesById.get(0).getCourseName();
Set<String> chapters = coursesById.stream().map(Course::getChapter).collect(Collectors.toSet());
courseInfos.add(new CourseInfoVO().setCourseId(courseId).setCourseName(courseName).setChapters(chapters));
}
}
return courseInfos;
}
@Override
public List<CourseDetailVO> getCourseDetail(CourseDetailReq courseDetailReq) {
List<CourseDetailVO> courseDetails = new ArrayList<>();
String courseName = courseDetailReq.getCourseName();
LambdaQueryWrapper<Course> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper
.eq(Course::getCourseName, courseName)
.ne(Course::getCourseStatus, CourseStatusEnums.DELETE);
boolean needChapter = courseDetailReq.isNeedChapter();
Set<String> chapters = courseDetailReq.getChapters();
if (!needChapter) {
// 不需要分组
List<Course> courses = list(queryWrapper);
courseDetails.add(CourseDetailVO.getCourseDetail(courseName, "all", courses));
} else {
// 需要分组
queryWrapper.in(CollUtil.isNotEmpty(chapters), Course::getChapter, chapters);
List<Course> courses = list(queryWrapper);
courseDetails.addAll(CourseDetailVO.getCourseDetails(courseName, courses));
}
return courseDetails;
}
@Override
@Transactional(rollbackFor = Exception.class)
public void batchLearned(BatchLearnedReq batchLearnedReq) {
LambdaQueryWrapper<Course> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper
.eq(Course::getCourseName, batchLearnedReq.getCourseName())
.eq(Course::getChapter, batchLearnedReq.getChapter())
.ge(Course::getSequence, batchLearnedReq.getStartSeq())
.le(Course::getSequence, batchLearnedReq.getEndSeq())
.ne(Course::getCourseStatus, CourseStatusEnums.DELETE);
List<Course> updateCourses = list(queryWrapper).stream()
.filter(it -> it.getCourseStatus().equals(CourseStatusEnums.LEARNING))
.peek(it -> {
it.setCourseStatus(CourseStatusEnums.LEARNED);
it.setUpdateTime(null);
})
.collect(Collectors.toList());
if (CollUtil.isEmpty(updateCourses)) {
throw new BusinessException("当前课程及章节下不存在未学习的内容");
}
updateBatchById(updateCourses);
}
@Override
public CourseListVO getCourseList(CourseListReq courseListReq) {
Long courseId = courseListReq.getCourseId();
Integer status = courseListReq.getStatus();
String chapter = courseListReq.getChapter();
LambdaQueryWrapper<Course> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper
.eq(Course::getCourseId, courseId);
if (Objects.isNull(status) || Objects.equals(status, 0)) {
queryWrapper.ne(Course::getCourseStatus, CourseStatusEnums.DELETE);
} else {
CourseStatusEnums courseStatus = CourseStatusEnums.of(status);
queryWrapper.eq(Course::getCourseStatus, courseStatus);
}
queryWrapper.eq(StrUtil.isNotEmpty(chapter), Course::getChapter, chapter);
List<Course> courses = list(queryWrapper);
if (CollUtil.isEmpty(courses)) {
throw new BusinessException("不存在当前的课程");
}
String courseName = courses.get(0).getCourseName();
TreeMap<String, List<CourseVO>> courseMap = courses.stream()
.map(Course::toCourseVO)
.collect(Collectors.groupingBy(CourseVO::getChapter, TreeMap::new, Collectors.toList()));
return new CourseListVO().setCourseId(courseId).setCourseName(courseName).setCourseMap(courseMap);
}
}

@ -0,0 +1,16 @@
package com.zyx.mpdemo.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zyx.mpdemo.mapper.UserMapper;
import com.zyx.mpdemo.model.entity.User;
import com.zyx.mpdemo.service.IUserService;
import org.springframework.stereotype.Service;
/**
* @author Yaxi.Zhang
* @since 2022/3/28 17:10
*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
}

@ -1,2 +1,52 @@
server: server:
port: 9001 port: 9001
spring:
application:
name: com-zyx-mpdemo
jackson:
date-format: yyyy-MM-dd HH:mm:ss
default-property-inclusion: non_null
time-zone: GMT+8
# 配置数据源信息
datasource:
type: com.zaxxer.hikari.HikariDataSource
# 配置连接数据库信息
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://81.68.117.201:3306/db_test?allowPublicKeyRetrieval=true&allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true
username: test
password: test
hikari:
pool-name: MpDemoPool
maximum-pool-size: 10
minimum-idle: 5
validation-timeout: 2500
idle-timeout: 30000
max-lifetime: 60000
connection-timeout: 30000
connection-test-query: SELECT 1
mybatis-plus:
# 设置MyBatis-Plus的全局配置
# global-config:
# db-config:
# # 设置统一的主键生成策略
# id-type: auto
# # 设置实体类所对应的表的统一前缀
# table-prefix: t_
configuration:
# mybatis日志输出
# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# 开启下划线转驼峰, MyBatisPlus默认是开启的
map-underscore-to-camel-case: true
# 开启返回map结果集的下划线转驼峰,
# https://www.jianshu.com/p/ae9fd5c3169c
# 需要配置ObjectWrapperFactoryConverter!!!
# 否则报错:
# Failed to bind properties under 'mybatis-plus.configuration.object-wrapper-factory' to org.apache.ibatis.reflection.wrapper.ObjectWrapperFactory
# object-wrapper-factory: com.baomidou.mybatisplus.extension.MybatisMapWrapperFactory
# 配置类型别名所对应的包, mapper.xml的resultType可以直接通过类名使用
type-aliases-package: com.zyx.mpdemo.model.entity
# 扫描通用枚举的包
type-enums-package: com.zyx.mpdemo.model.enums
# 默认值为 classpath*:/mapper/**/*.xml, 如果mapper放在其他的位置, 需要自己配置(这里可配可不配)
mapper-locations: classpath*:/mapper/**/*.xml

@ -0,0 +1,27 @@
<?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.zyx.mpdemo.mapper.CourseMapper">
<resultMap id="BaseResultMap" type="com.zyx.mpdemo.model.entity.Course">
<id property="id" column="id" jdbcType="BIGINT"/>
<result property="courseId" column="course_id" jdbcType="BIGINT"/>
<result property="courseName" column="course_name" jdbcType="VARCHAR"/>
<result property="chapter" column="chapter" jdbcType="VARCHAR"/>
<result property="sequence" column="sequence" jdbcType="VARCHAR"/>
<result property="courseHours" column="course_hours" jdbcType="INTEGER"/>
<result property="courseMinutes" column="course_minutes" jdbcType="INTEGER"/>
<result property="courseSeconds" column="course_seconds" jdbcType="INTEGER"/>
<result property="courseStatus" column="course_status" jdbcType="TINYINT"/>
<result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
<result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
</resultMap>
<sql id="Base_Column_List">
id,course_id,course_name,
chapter,sequence,course_hours,
course_minutes,course_seconds,course_status,
create_time,update_time
</sql>
</mapper>

@ -0,0 +1,17 @@
<?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.zyx.mpdemo.mapper.UserMapper">
<!--Map<String, Object> selectMapById(Long id);-->
<select id="selectMapByAge" resultType="map">
select id,user_name,age,email from t_user where age = #{age}
</select>
<!--Page<User> selectPageVo(@Param("page") Page<User> page, @Param("age") Integer age);-->
<select id="selectPageVo" resultType="User">
select uid,user_name,age,email from t_user where age > #{age}
</select>
</mapper>
Loading…
Cancel
Save