Refactor project structure and enhance functionality
- Renamed XML mapper files for consistency. - Added new fields `is_admin` and `is_banned` to the `Reader` entity and updated the database schema. - Introduced `AuthCheck` annotation for method-level authorization. - Implemented JWT utility for token generation and validation. - Enhanced service and controller layers for `Book`, `Reader`, and `Orders` with new methods and improved error handling. - Added global exception handling for better API response management. - Updated `pom.xml` to include new dependencies for JWT and Spring Security.
This commit is contained in:
parent
81e6212acd
commit
0f5defb2d0
File diff suppressed because it is too large
Load Diff
19
pom.xml
19
pom.xml
@ -63,11 +63,11 @@
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/com.github.xiaoymin/knife4j-openapi3-jakarta-spring-boot-starter -->
|
||||
<!-- https://mvnrepository.com/artifact/com.github.xingfudeshi/knife4j-openapi3-jakarta-spring-boot-starter -->
|
||||
<dependency>
|
||||
<groupId>com.github.xiaoymin</groupId>
|
||||
<groupId>com.github.xingfudeshi</groupId>
|
||||
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
|
||||
<version>4.5.0</version>
|
||||
<version>4.6.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/io.swagger/swagger-annotations -->
|
||||
@ -88,6 +88,19 @@
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/com.auth0/java-jwt -->
|
||||
<dependency>
|
||||
<groupId>com.auth0</groupId>
|
||||
<artifactId>java-jwt</artifactId>
|
||||
<version>4.5.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-crypto -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-crypto</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
|
||||
@ -0,0 +1,17 @@
|
||||
package com.grtsinry43.bookmanagement.annotation;
|
||||
|
||||
import com.grtsinry43.bookmanagement.common.UserRole;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* @author grtsinry43
|
||||
* @date 2024/9/8 14:41
|
||||
* @description 少年负壮气,奋烈自有时!
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface AuthCheck {
|
||||
UserRole requiredRole() default UserRole.NOT_LOGIN;
|
||||
}
|
||||
@ -0,0 +1,114 @@
|
||||
package com.grtsinry43.bookmanagement.aop;
|
||||
|
||||
import com.grtsinry43.bookmanagement.annotation.AuthCheck;
|
||||
import com.grtsinry43.bookmanagement.common.BusinessException;
|
||||
import com.grtsinry43.bookmanagement.common.ErrorCode;
|
||||
import com.grtsinry43.bookmanagement.common.UserRole;
|
||||
import com.grtsinry43.bookmanagement.entity.Reader;
|
||||
import com.grtsinry43.bookmanagement.service.ReaderService;
|
||||
import com.grtsinry43.bookmanagement.util.JwtUtil;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
|
||||
/**
|
||||
* @author grtsinry43
|
||||
* @date 2024/9/8 14:48
|
||||
* @description 少年负壮气,奋烈自有时!
|
||||
*/
|
||||
@Component
|
||||
public class AuthInterceptor implements HandlerInterceptor {
|
||||
|
||||
private final ReaderService readerService;
|
||||
|
||||
public AuthInterceptor(ReaderService readerService) {
|
||||
this.readerService = readerService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||
if (handler instanceof HandlerMethod) {
|
||||
HandlerMethod method = (HandlerMethod) handler;
|
||||
AuthCheck authCheck = method.getMethodAnnotation(AuthCheck.class);
|
||||
if (authCheck != null) {
|
||||
// 根据传入的注解获取所需的权限
|
||||
UserRole requiredRole = authCheck.requiredRole();
|
||||
String token = request.getHeader("Authorization");
|
||||
|
||||
if (requiredRole == UserRole.NOT_LOGIN) {
|
||||
// 未登录可以访问无需登录的接口
|
||||
return true;
|
||||
}
|
||||
|
||||
if (token == null || token.isEmpty() || !token.startsWith("Bearer ")) {
|
||||
// 未登录访问需要登录的接口,返回未授权
|
||||
System.out.println("Token missing or invalid format for: " + request.getRequestURI());
|
||||
throw new BusinessException(ErrorCode.NOT_LOGIN);
|
||||
}
|
||||
token = token.substring(7);
|
||||
|
||||
// 先判断是否过期,catch 异常说明 token 无效
|
||||
try {
|
||||
if (JwtUtil.isTokenExpired(token)) {
|
||||
throw new BusinessException(ErrorCode.NOT_LOGIN);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new BusinessException(ErrorCode.NOT_LOGIN);
|
||||
}
|
||||
|
||||
String userIdStr = JwtUtil.getUserFromToken(token);
|
||||
if (userIdStr == null) {
|
||||
throw new BusinessException(ErrorCode.NOT_LOGIN);
|
||||
}
|
||||
|
||||
Integer userId;
|
||||
try {
|
||||
userId = Integer.parseInt(userIdStr);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new BusinessException(ErrorCode.PARAMS_ERROR);
|
||||
}
|
||||
|
||||
System.out.println("User ID: " + userId + " accessing: " + request.getRequestURI());
|
||||
Reader user = readerService.getReaderById(userId);
|
||||
if (user == null) {
|
||||
// This case might mean the user was deleted after token issuance
|
||||
throw new BusinessException(ErrorCode.NOT_FOUND);
|
||||
}
|
||||
|
||||
// Check if user is banned first, unless they are an admin trying to access an admin-only route.
|
||||
// An admin should be able to access admin routes even if banned, to potentially unban themselves or others.
|
||||
// However, a banned admin should not access general user routes.
|
||||
|
||||
if (user.getIsBanned() != null && user.getIsBanned()) {
|
||||
// If user is banned, they cannot access any route unless it's an admin route and they are an admin.
|
||||
if (!(user.getIsAdmin() != null && user.getIsAdmin() && requiredRole == UserRole.ADMIN)) {
|
||||
System.out.println("Banned user ID: " + userId + " attempted to access: " + request.getRequestURI());
|
||||
throw new BusinessException(ErrorCode.UNAUTHORIZED);
|
||||
}
|
||||
}
|
||||
|
||||
request.setAttribute("userId", userId);
|
||||
|
||||
if (user.getIsAdmin() != null && user.getIsAdmin()) {
|
||||
// 管理员可以访问所有接口 (already set attribute, so just return true)
|
||||
System.out.println("Admin user ID: " + userId + " accessed: " + request.getRequestURI());
|
||||
return true;
|
||||
}
|
||||
|
||||
// At this point, user is not an admin.
|
||||
if (requiredRole == UserRole.ADMIN) {
|
||||
// 非管理员访问管理员接口,返回无权限
|
||||
System.out.println("Non-admin user ID: " + userId + " attempted to access admin route: " + request.getRequestURI());
|
||||
throw new BusinessException(ErrorCode.UNAUTHORIZED);
|
||||
}
|
||||
|
||||
// For regular users, already checked for ban status above.
|
||||
// If not banned and not admin, and route doesn't require admin, access is granted.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,50 @@
|
||||
package com.grtsinry43.bookmanagement.common;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @Author: grtsinry43
|
||||
* @Date: 2024/7/13 上午 12:27
|
||||
* 这里规定返回消息格式,所有的正确响应 HTTP 状态码都是 200,只会根据 code 字段和 msg 来提供错误信息
|
||||
*/
|
||||
@Data
|
||||
public class ApiResponse<T> implements Serializable {
|
||||
private Integer code;
|
||||
private String msg = "";
|
||||
private T data;
|
||||
|
||||
/**
|
||||
* 含有数据的成功响应
|
||||
*
|
||||
* @param data 返回的数据
|
||||
* @param <T> 数据类型
|
||||
*/
|
||||
public static <T> ApiResponse<T> success(T data) {
|
||||
ApiResponse<T> response = new ApiResponse<>();
|
||||
response.setCode(0);
|
||||
response.setData(data);
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* 不含数据的成功响应
|
||||
*/
|
||||
public static <T> ApiResponse<T> success() {
|
||||
return success(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 失败响应,包含错误码和错误信息
|
||||
*
|
||||
* @param code 错误码
|
||||
* @param msg 错误信息
|
||||
*/
|
||||
public static <T> ApiResponse<T> error(Integer code, String msg) {
|
||||
ApiResponse<T> response = new ApiResponse<>();
|
||||
response.setCode(code);
|
||||
response.setMsg(msg);
|
||||
return response;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
package com.grtsinry43.bookmanagement.common;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* @author grtsinry43
|
||||
* @date 2024/9/8 14:55
|
||||
* @description 少年负壮气,奋烈自有时!
|
||||
*/
|
||||
@Getter
|
||||
public class BusinessException extends RuntimeException {
|
||||
private ErrorCode errorCode;
|
||||
private String message;
|
||||
|
||||
public BusinessException(ErrorCode errorCode) {
|
||||
this.errorCode = errorCode;
|
||||
this.message = errorCode.getMessage();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
package com.grtsinry43.bookmanagement.common;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* @author grtsinry43
|
||||
* @date 2024/9/1 15:44
|
||||
* @description 少年负壮气,奋烈自有时!
|
||||
*/
|
||||
@Getter
|
||||
public enum ErrorCode {
|
||||
PARAMS_ERROR(400, "参数错误"),
|
||||
NOT_LOGIN(401, "未登录或登录已过期"),
|
||||
INVALID_DATA(402, "无效数据"),
|
||||
UNAUTHORIZED(403, "你没有访问该资源的权限"),
|
||||
BANNED(40301, "你没有访问该资源的权限"),
|
||||
NOT_FOUND(404, "请求的资源不存在"),
|
||||
METHOD_NOT_ALLOWED(405, "请求方法不支持"),
|
||||
INTERNAL_SERVER_ERROR(500, "服务器内部错误");
|
||||
|
||||
private final int code;
|
||||
private final String msg;
|
||||
|
||||
ErrorCode(int code, String msg) {
|
||||
this.code = code;
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return msg;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
package com.grtsinry43.bookmanagement.common;
|
||||
|
||||
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 用户角色枚举
|
||||
*
|
||||
* @author grtsinry43
|
||||
* @date 2024/9/1 16:14
|
||||
*/
|
||||
@Getter
|
||||
public enum UserRole {
|
||||
NOT_LOGIN("未登录", "not_login"),
|
||||
USER("默认角色", "user"),
|
||||
ADMIN("管理员角色", "admin"),
|
||||
BAN("被封禁用户", "ban");
|
||||
|
||||
private final String text;
|
||||
|
||||
private final String value;
|
||||
|
||||
UserRole(String text, String value) {
|
||||
this.text = text;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取值列表
|
||||
*/
|
||||
public static List<String> getValues() {
|
||||
return Arrays.stream(values()).map(item -> item.value).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 value 获取枚举
|
||||
*/
|
||||
public static UserRole getEnumByValue(String value) {
|
||||
if (ObjectUtils.isEmpty(value)) {
|
||||
return null;
|
||||
}
|
||||
for (UserRole anEnum : UserRole.values()) {
|
||||
if (anEnum.value.equals(value)) {
|
||||
return anEnum;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,11 +1,20 @@
|
||||
package com.grtsinry43.bookmanagement.controller;
|
||||
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import com.grtsinry43.bookmanagement.annotation.AuthCheck;
|
||||
import com.grtsinry43.bookmanagement.common.ApiResponse;
|
||||
import com.grtsinry43.bookmanagement.common.BusinessException;
|
||||
import com.grtsinry43.bookmanagement.common.ErrorCode;
|
||||
import com.grtsinry43.bookmanagement.common.UserRole;
|
||||
import com.grtsinry43.bookmanagement.entity.Book;
|
||||
import com.grtsinry43.bookmanagement.service.BookService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 前端控制器
|
||||
* 前端控制器
|
||||
* </p>
|
||||
*
|
||||
* @author grtsinry43
|
||||
@ -15,4 +24,69 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
@RequestMapping("/book")
|
||||
public class BookController {
|
||||
|
||||
@Autowired
|
||||
private BookService bookService;
|
||||
|
||||
@GetMapping("/all")
|
||||
public ApiResponse<List<Book>> getAllBooks() {
|
||||
List<Book> books = bookService.getAllBooks();
|
||||
return ApiResponse.success(books);
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public ApiResponse<Book> getBookById(@PathVariable Integer id) {
|
||||
Book book = bookService.getBookById(id);
|
||||
if (book != null) {
|
||||
return ApiResponse.success(book);
|
||||
} else {
|
||||
throw new BusinessException(ErrorCode.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/search/title")
|
||||
@AuthCheck(requiredRole = UserRole.USER)
|
||||
public ApiResponse<List<Book>> searchBooksByTitle(@RequestParam String title) {
|
||||
List<Book> books = bookService.getBooksByTitle(title);
|
||||
return ApiResponse.success(books);
|
||||
}
|
||||
|
||||
@GetMapping("/search/author")
|
||||
@AuthCheck(requiredRole = UserRole.USER)
|
||||
public ApiResponse<List<Book>> searchBooksByAuthor(@RequestParam String authorName) {
|
||||
List<Book> books = bookService.getBooksByAuthor(authorName);
|
||||
return ApiResponse.success(books);
|
||||
}
|
||||
|
||||
@GetMapping("/search/publisher")
|
||||
@AuthCheck(requiredRole = UserRole.USER)
|
||||
public ApiResponse<List<Book>> searchBooksByPublisher(@RequestParam String publisherName) {
|
||||
List<Book> books = bookService.getBooksByPublisher(publisherName);
|
||||
return ApiResponse.success(books);
|
||||
}
|
||||
|
||||
@PostMapping("/admin/add")
|
||||
@AuthCheck(requiredRole = UserRole.ADMIN)
|
||||
public ApiResponse<Book> addBook(@RequestBody Book book) {
|
||||
bookService.addBook(book);
|
||||
return ApiResponse.success(book);
|
||||
|
||||
}
|
||||
|
||||
@PutMapping("/admin/update")
|
||||
@AuthCheck(requiredRole = UserRole.ADMIN)
|
||||
public ApiResponse<Book> updateBook(@RequestBody Book book) {
|
||||
|
||||
bookService.updateBook(book);
|
||||
return ApiResponse.success(book);
|
||||
|
||||
}
|
||||
|
||||
@DeleteMapping("/admin/delete/{id}")
|
||||
@AuthCheck(requiredRole = UserRole.ADMIN)
|
||||
public ApiResponse<Void> deleteBook(@PathVariable Integer id) {
|
||||
|
||||
bookService.deleteBook(id);
|
||||
return ApiResponse.success(null);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,71 @@
|
||||
package com.grtsinry43.bookmanagement.controller;
|
||||
|
||||
import com.grtsinry43.bookmanagement.common.ApiResponse;
|
||||
import com.grtsinry43.bookmanagement.common.BusinessException;
|
||||
import jakarta.validation.ConstraintViolationException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.MissingServletRequestParameterException;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
|
||||
/**
|
||||
* @author grtsinry43
|
||||
* @date 2024/7/13 上午12:29
|
||||
* @description 规定触发异常时的返回格式,依然是HTTP状态码200,只会根据code字段和msg来提供错误信息
|
||||
*/
|
||||
@Slf4j
|
||||
@ControllerAdvice
|
||||
public class GlobalExceptionHandler {
|
||||
/**
|
||||
* 处理缺少请求参数异常
|
||||
*/
|
||||
@ExceptionHandler(MissingServletRequestParameterException.class)
|
||||
public ResponseEntity<ApiResponse<Object>> handleMissingServletRequestParameterException(Exception ex) {
|
||||
String errorMessage = "缺少请求参数:" + ex.getMessage();
|
||||
ApiResponse<Object> apiResponse = ApiResponse.error(400, errorMessage);
|
||||
return new ResponseEntity<>(apiResponse, HttpStatus.OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理参数校验异常(注释声明即可)
|
||||
*/
|
||||
@ExceptionHandler(ConstraintViolationException.class)
|
||||
public ResponseEntity<ApiResponse<Object>> handleConstraintViolationException(ConstraintViolationException ex) {
|
||||
String errorMessage = ex.getMessage();
|
||||
ApiResponse<Object> apiResponse = ApiResponse.error(400, errorMessage);
|
||||
return new ResponseEntity<>(apiResponse, HttpStatus.OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理参数校验异常(注释声明即可)
|
||||
*/
|
||||
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||||
public ResponseEntity<ApiResponse<Object>> handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) {
|
||||
ApiResponse<Object> apiResponse = ApiResponse.error(400, "参数传递有误或者缺少参数");
|
||||
return new ResponseEntity<>(apiResponse, HttpStatus.OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理业务逻辑异常(注释声明即可)
|
||||
*/
|
||||
@ExceptionHandler(BusinessException.class)
|
||||
public ResponseEntity<ApiResponse<Object>> handleBusinessException(BusinessException ex) {
|
||||
String errorMessage = ex.getMessage();
|
||||
ApiResponse<Object> apiResponse = ApiResponse.error(ex.getErrorCode().getCode(), errorMessage);
|
||||
return new ResponseEntity<>(apiResponse, HttpStatus.OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理其他异常(注释声明即可)
|
||||
*/
|
||||
@ExceptionHandler(Exception.class)
|
||||
public ResponseEntity<ApiResponse<Object>> handleException(Exception ex) {
|
||||
String errorMessage = ex.getMessage();
|
||||
log.error("系统异常: {}", errorMessage, ex); // 使用日志框架记录异常,包含完整堆栈
|
||||
ApiResponse<Object> apiResponse = ApiResponse.error(500, "服务器发生内部错误,您可以尝试刷新,如果问题依旧,请联系我们");
|
||||
return new ResponseEntity<>(apiResponse, HttpStatus.OK);
|
||||
}
|
||||
}
|
||||
@ -1,11 +1,24 @@
|
||||
package com.grtsinry43.bookmanagement.controller;
|
||||
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import com.grtsinry43.bookmanagement.annotation.AuthCheck;
|
||||
import com.grtsinry43.bookmanagement.common.ApiResponse;
|
||||
import com.grtsinry43.bookmanagement.common.BusinessException;
|
||||
import com.grtsinry43.bookmanagement.common.ErrorCode;
|
||||
import com.grtsinry43.bookmanagement.common.UserRole;
|
||||
import com.grtsinry43.bookmanagement.dto.CreateOrderRequest;
|
||||
import com.grtsinry43.bookmanagement.entity.OrderItem;
|
||||
import com.grtsinry43.bookmanagement.entity.Orders;
|
||||
import com.grtsinry43.bookmanagement.service.OrderItemService; // Keep for future use if OrderItem specific endpoints are added
|
||||
import com.grtsinry43.bookmanagement.service.OrdersService;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 前端控制器
|
||||
* 订单前端控制器
|
||||
* </p>
|
||||
*
|
||||
* @author grtsinry43
|
||||
@ -15,4 +28,121 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
@RequestMapping("/orders")
|
||||
public class OrdersController {
|
||||
|
||||
@Autowired
|
||||
private OrdersService ordersService;
|
||||
|
||||
// @Autowired
|
||||
// private OrderItemService orderItemService; // 如果需要单独操作订单项,则保留
|
||||
|
||||
/**
|
||||
* 顾客:创建新订单
|
||||
* @param createOrderRequest 包含订单信息和订单项列表的请求体
|
||||
* @param request HTTP请求对象,用于获取用户ID
|
||||
* @return 包含创建的订单信息的API响应
|
||||
*/
|
||||
@PostMapping("/create")
|
||||
@AuthCheck(requiredRole = UserRole.USER) // 需要用户登录才能创建订单
|
||||
public ApiResponse<Orders> createOrder(@RequestBody CreateOrderRequest createOrderRequest, HttpServletRequest request) {
|
||||
// 从HttpServletRequest中获取用户ID
|
||||
Object userIdObject = request.getAttribute("userId");
|
||||
if (userIdObject == null) {
|
||||
throw new BusinessException(ErrorCode.NOT_LOGIN);
|
||||
}
|
||||
Integer userId = (Integer) userIdObject;
|
||||
|
||||
// 基本验证:订单项不能为空
|
||||
if (createOrderRequest.getItems() == null || createOrderRequest.getItems().isEmpty()) {
|
||||
throw new BusinessException(ErrorCode.PARAMS_ERROR);
|
||||
}
|
||||
|
||||
Orders orderToCreate = createOrderRequest.getOrder();
|
||||
if (orderToCreate == null) {
|
||||
// 如果请求中没有order部分,或者需要初始化一个
|
||||
orderToCreate = new Orders();
|
||||
}
|
||||
// 设置订单的读者ID为当前登录用户的ID
|
||||
orderToCreate.setReaderId(userId);
|
||||
|
||||
// 调用服务创建订单
|
||||
// 服务层中的 createOrder 方法应该处理库存检查等业务逻辑,并在发生错误时抛出 BusinessException
|
||||
Orders createdOrder = ordersService.createOrder(orderToCreate, createOrderRequest.getItems());
|
||||
return ApiResponse.success(createdOrder);
|
||||
}
|
||||
|
||||
/**
|
||||
* 顾客:查看自己的订单列表
|
||||
* @param request HTTP请求对象,用于获取用户ID
|
||||
* @return 包含用户订单列表的API响应
|
||||
*/
|
||||
@GetMapping("/my-orders") // 移除了{readerId}路径参数
|
||||
@AuthCheck(requiredRole = UserRole.USER) // 需要用户登录才能查看订单
|
||||
public ApiResponse<List<Orders>> getMyOrders(HttpServletRequest request) {
|
||||
// 从HttpServletRequest中获取用户ID
|
||||
Object userIdObject = request.getAttribute("userId");
|
||||
if (userIdObject == null) {
|
||||
throw new BusinessException(ErrorCode.NOT_LOGIN);
|
||||
}
|
||||
Integer userId = (Integer) userIdObject;
|
||||
|
||||
List<Orders> orders = ordersService.getOrdersByReaderId(userId);
|
||||
return ApiResponse.success(orders);
|
||||
}
|
||||
|
||||
/**
|
||||
* 顾客和管理员:查看特定订单详情
|
||||
* (对于顾客,应在服务层或此处增加逻辑,校验订单是否属于该顾客,除非拦截器已处理)
|
||||
* @param orderId 订单ID
|
||||
* @param request HTTP请求对象 (如果需要根据用户角色或ID进行权限校验)
|
||||
* @return 包含订单详情的API响应
|
||||
*/
|
||||
@GetMapping("/{orderId}")
|
||||
@AuthCheck(requiredRole = UserRole.USER) // 需要用户登录才能查看订单详情
|
||||
public ApiResponse<Orders> getOrderDetails(@PathVariable Integer orderId, HttpServletRequest request) {
|
||||
// 示例:如果需要基于用户ID的权限检查,可以从request中获取userId
|
||||
Object userIdObject = request.getAttribute("userId");
|
||||
Integer currentUserId = (userIdObject != null) ? (Integer) userIdObject : null;
|
||||
// TODO: 根据业务需求,添加权限校验逻辑,例如检查订单是否属于当前用户(如果非管理员)
|
||||
|
||||
Orders order = ordersService.getOrderById(orderId);
|
||||
if (order == null) {
|
||||
throw new BusinessException(ErrorCode.NOT_FOUND);
|
||||
}
|
||||
if (order.getReaderId() != null && !order.getReaderId().equals(currentUserId)) {
|
||||
// 如果订单属于其他用户,且当前用户不是管理员,则抛出权限异常
|
||||
throw new BusinessException(ErrorCode.UNAUTHORIZED);
|
||||
}
|
||||
// 考虑:如果用户不是管理员,且订单不属于该用户,也应抛出权限异常
|
||||
return ApiResponse.success(order);
|
||||
}
|
||||
|
||||
/**
|
||||
* 管理员:查看所有订单列表
|
||||
* (假设已有管理员权限拦截器)
|
||||
* @return 包含所有订单列表的API响应
|
||||
*/
|
||||
@GetMapping("/admin/all")
|
||||
@AuthCheck(requiredRole = UserRole.ADMIN) // 需要管理员权限才能查看所有订单
|
||||
public ApiResponse<List<Orders>> getAllOrders() {
|
||||
List<Orders> orders = ordersService.getAllOrders();
|
||||
return ApiResponse.success(orders);
|
||||
}
|
||||
|
||||
/**
|
||||
* 管理员:更新订单状态
|
||||
* (假设已有管理员权限拦截器)
|
||||
* @param orderId 订单ID
|
||||
* @param status 新的订单状态
|
||||
* @return 操作结果的API响应
|
||||
*/
|
||||
@PutMapping("/admin/update-status/{orderId}")
|
||||
@AuthCheck(requiredRole = UserRole.ADMIN) // 需要管理员权限才能更新订单状态
|
||||
public ApiResponse<String> updateOrderStatus(@PathVariable Integer orderId, @RequestParam String status) {
|
||||
// TODO: 可以增加对status参数有效性的校验
|
||||
if (status == null || status.trim().isEmpty()) {
|
||||
throw new BusinessException(ErrorCode.PARAMS_ERROR);
|
||||
}
|
||||
ordersService.updateOrderStatus(orderId, status);
|
||||
// 更新成功,通常返回成功的消息,data部分可以为null或包含更新后的对象(如果服务层返回)
|
||||
return ApiResponse.success(null);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,11 +1,28 @@
|
||||
package com.grtsinry43.bookmanagement.controller;
|
||||
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import com.grtsinry43.bookmanagement.annotation.AuthCheck;
|
||||
import com.grtsinry43.bookmanagement.common.ApiResponse;
|
||||
import com.grtsinry43.bookmanagement.common.BusinessException;
|
||||
import com.grtsinry43.bookmanagement.common.ErrorCode;
|
||||
import com.grtsinry43.bookmanagement.common.UserRole;
|
||||
import com.grtsinry43.bookmanagement.dto.LoginRequest;
|
||||
import com.grtsinry43.bookmanagement.dto.RegisterRequest;
|
||||
import com.grtsinry43.bookmanagement.entity.Reader;
|
||||
import com.grtsinry43.bookmanagement.service.ReaderService;
|
||||
import com.grtsinry43.bookmanagement.util.JwtUtil;
|
||||
import com.grtsinry43.bookmanagement.vo.ReaderVO;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 前端控制器
|
||||
* 前端控制器
|
||||
* </p>
|
||||
*
|
||||
* @author grtsinry43
|
||||
@ -15,4 +32,102 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
@RequestMapping("/reader")
|
||||
public class ReaderController {
|
||||
|
||||
private final ReaderService readerService;
|
||||
|
||||
@Autowired
|
||||
public ReaderController(ReaderService readerService) {
|
||||
this.readerService = readerService;
|
||||
}
|
||||
|
||||
private ReaderVO convertToReaderVO(Reader reader) {
|
||||
if (reader == null) {
|
||||
return null;
|
||||
}
|
||||
ReaderVO readerVO = new ReaderVO();
|
||||
BeanUtils.copyProperties(reader, readerVO);
|
||||
return readerVO;
|
||||
}
|
||||
|
||||
@PostMapping("/register")
|
||||
@AuthCheck(requiredRole = UserRole.NOT_LOGIN)
|
||||
public ApiResponse<ReaderVO> registerReader(@RequestBody RegisterRequest registerRequest) {
|
||||
if (registerRequest.getUsername() == null || registerRequest.getPassword() == null ||
|
||||
registerRequest.getUsername().trim().isEmpty() || registerRequest.getPassword().isEmpty()) {
|
||||
throw new BusinessException(ErrorCode.PARAMS_ERROR);
|
||||
}
|
||||
Reader reader = new Reader();
|
||||
BeanUtils.copyProperties(registerRequest, reader);
|
||||
readerService.registerReader(reader);
|
||||
return ApiResponse.success(convertToReaderVO(reader));
|
||||
}
|
||||
|
||||
@PostMapping("/login")
|
||||
@AuthCheck(requiredRole = UserRole.NOT_LOGIN)
|
||||
public ApiResponse<Map<String, Object>> login(@RequestBody LoginRequest loginRequest) {
|
||||
if (loginRequest.getUsername() == null || loginRequest.getPassword() == null ||
|
||||
loginRequest.getUsername().trim().isEmpty() || loginRequest.getPassword().isEmpty()) {
|
||||
throw new BusinessException(ErrorCode.PARAMS_ERROR);
|
||||
}
|
||||
|
||||
Reader loggedInReader = readerService.login(loginRequest.getUsername(), loginRequest.getPassword());
|
||||
String token = JwtUtil.generateToken(loggedInReader.getReaderId().toString());
|
||||
|
||||
Map<String, Object> responseData = new HashMap<>();
|
||||
responseData.put("token", token);
|
||||
responseData.put("user", convertToReaderVO(loggedInReader));
|
||||
|
||||
return ApiResponse.success(responseData);
|
||||
}
|
||||
|
||||
@GetMapping("/admin/all")
|
||||
@AuthCheck(requiredRole = UserRole.ADMIN)
|
||||
public ApiResponse<List<ReaderVO>> getAllReaders() {
|
||||
List<Reader> readers = readerService.getAllReaders();
|
||||
List<ReaderVO> readerVOs = readers.stream()
|
||||
.map(this::convertToReaderVO)
|
||||
.collect(Collectors.toList());
|
||||
return ApiResponse.success(readerVOs);
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
@AuthCheck(requiredRole = UserRole.USER)
|
||||
public ApiResponse<ReaderVO> getReaderById(@PathVariable Integer id) {
|
||||
Reader reader = readerService.getReaderById(id);
|
||||
if (reader == null) {
|
||||
throw new BusinessException(ErrorCode.NOT_FOUND);
|
||||
}
|
||||
return ApiResponse.success(convertToReaderVO(reader));
|
||||
}
|
||||
|
||||
@PutMapping("/admin/{id}/make-admin")
|
||||
@AuthCheck(requiredRole = UserRole.ADMIN)
|
||||
public ApiResponse<ReaderVO> makeAdmin(@PathVariable Integer id) {
|
||||
readerService.updateUserAdminStatus(id, true);
|
||||
Reader updatedReader = readerService.getReaderById(id);
|
||||
return ApiResponse.success(convertToReaderVO(updatedReader));
|
||||
}
|
||||
|
||||
@PutMapping("/admin/{id}/remove-admin")
|
||||
@AuthCheck(requiredRole = UserRole.ADMIN)
|
||||
public ApiResponse<ReaderVO> removeAdmin(@PathVariable Integer id) {
|
||||
readerService.updateUserAdminStatus(id, false);
|
||||
Reader updatedReader = readerService.getReaderById(id);
|
||||
return ApiResponse.success(convertToReaderVO(updatedReader));
|
||||
}
|
||||
|
||||
@PutMapping("/admin/{id}/ban")
|
||||
@AuthCheck(requiredRole = UserRole.ADMIN)
|
||||
public ApiResponse<ReaderVO> banUser(@PathVariable Integer id) {
|
||||
readerService.updateUserBanStatus(id, true);
|
||||
Reader updatedReader = readerService.getReaderById(id);
|
||||
return ApiResponse.success(convertToReaderVO(updatedReader));
|
||||
}
|
||||
|
||||
@PutMapping("/admin/{id}/unban")
|
||||
@AuthCheck(requiredRole = UserRole.ADMIN)
|
||||
public ApiResponse<ReaderVO> unbanUser(@PathVariable Integer id) {
|
||||
readerService.updateUserBanStatus(id, false);
|
||||
Reader updatedReader = readerService.getReaderById(id);
|
||||
return ApiResponse.success(convertToReaderVO(updatedReader));
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,20 @@
|
||||
package com.grtsinry43.bookmanagement.dto;
|
||||
|
||||
import com.grtsinry43.bookmanagement.entity.OrderItem;
|
||||
import com.grtsinry43.bookmanagement.entity.Orders;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 创建订单请求体
|
||||
*/
|
||||
@Data
|
||||
public class CreateOrderRequest implements Serializable {
|
||||
private Orders order;
|
||||
private List<OrderItem> items;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
package com.grtsinry43.bookmanagement.dto;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 登录请求体
|
||||
*/
|
||||
public class LoginRequest implements Serializable {
|
||||
private String username;
|
||||
private String password;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
package com.grtsinry43.bookmanagement.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 注册请求体
|
||||
*/
|
||||
@Data
|
||||
public class RegisterRequest implements Serializable {
|
||||
private String username;
|
||||
private String password;
|
||||
private String email;
|
||||
private String phone;
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
||||
|
||||
@ -21,19 +21,30 @@ import java.io.Serializable;
|
||||
@Getter
|
||||
@Setter
|
||||
@ToString
|
||||
@ApiModel(value = "Reader对象", description = "")
|
||||
@ApiModel(value = "Reader对象", description = "读者实体类")
|
||||
public class Reader implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@ApiModelProperty("读者ID")
|
||||
@TableId(value = "reader_id", type = IdType.AUTO)
|
||||
private Integer readerId;
|
||||
|
||||
@ApiModelProperty("用户名")
|
||||
private String username;
|
||||
|
||||
@ApiModelProperty("密码")
|
||||
private String password;
|
||||
|
||||
@ApiModelProperty("邮箱")
|
||||
private String email;
|
||||
|
||||
@ApiModelProperty("电话")
|
||||
private String phone;
|
||||
|
||||
@ApiModelProperty("是否为管理员")
|
||||
private Boolean isAdmin = false;
|
||||
|
||||
@ApiModelProperty("是否被封禁")
|
||||
private Boolean isBanned = false;
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ package com.grtsinry43.bookmanagement.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.grtsinry43.bookmanagement.entity.Author;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@ -11,6 +12,7 @@ import com.grtsinry43.bookmanagement.entity.Author;
|
||||
* @author grtsinry43
|
||||
* @since 2025-05-19
|
||||
*/
|
||||
@Mapper
|
||||
public interface AuthorMapper extends BaseMapper<Author> {
|
||||
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ package com.grtsinry43.bookmanagement.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.grtsinry43.bookmanagement.entity.BookAuthor;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@ -11,6 +12,7 @@ import com.grtsinry43.bookmanagement.entity.BookAuthor;
|
||||
* @author grtsinry43
|
||||
* @since 2025-05-19
|
||||
*/
|
||||
@Mapper
|
||||
public interface BookAuthorMapper extends BaseMapper<BookAuthor> {
|
||||
|
||||
}
|
||||
|
||||
@ -2,6 +2,10 @@ package com.grtsinry43.bookmanagement.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.grtsinry43.bookmanagement.entity.Book;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@ -11,6 +15,21 @@ import com.grtsinry43.bookmanagement.entity.Book;
|
||||
* @author grtsinry43
|
||||
* @since 2025-05-19
|
||||
*/
|
||||
@Mapper
|
||||
public interface BookMapper extends BaseMapper<Book> {
|
||||
Book findById(@Param("bookId") Integer bookId);
|
||||
|
||||
List<Book> findAll();
|
||||
|
||||
List<Book> findByTitle(@Param("title") String title);
|
||||
|
||||
List<Book> findByAuthor(@Param("authorName") String authorName);
|
||||
|
||||
List<Book> findByPublisher(@Param("publisherName") String publisherName);
|
||||
|
||||
int insert(Book book);
|
||||
|
||||
int update(Book book);
|
||||
|
||||
int delete(@Param("bookId") Integer bookId);
|
||||
}
|
||||
|
||||
@ -2,6 +2,10 @@ package com.grtsinry43.bookmanagement.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.grtsinry43.bookmanagement.entity.OrderItem;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@ -11,6 +15,12 @@ import com.grtsinry43.bookmanagement.entity.OrderItem;
|
||||
* @author grtsinry43
|
||||
* @since 2025-05-19
|
||||
*/
|
||||
@Mapper
|
||||
public interface OrderItemMapper extends BaseMapper<OrderItem> {
|
||||
List<OrderItem> findByOrderId(@Param("orderId") Integer orderId);
|
||||
|
||||
int insert(OrderItem orderItem);
|
||||
|
||||
// For batch insert if needed
|
||||
// int insertBatch(@Param("list") List<OrderItem> orderItems);
|
||||
}
|
||||
|
||||
@ -2,6 +2,10 @@ package com.grtsinry43.bookmanagement.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.grtsinry43.bookmanagement.entity.Orders;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@ -11,6 +15,16 @@ import com.grtsinry43.bookmanagement.entity.Orders;
|
||||
* @author grtsinry43
|
||||
* @since 2025-05-19
|
||||
*/
|
||||
@Mapper
|
||||
public interface OrdersMapper extends BaseMapper<Orders> {
|
||||
Orders findById(@Param("orderId") Integer orderId);
|
||||
|
||||
List<Orders> findAll(); // For admin
|
||||
|
||||
List<Orders> findByReaderId(@Param("readerId") Integer readerId);
|
||||
|
||||
// Consider adding findByDateRange, findByStatus etc. if needed
|
||||
int insert(Orders order);
|
||||
|
||||
int updateStatus(@Param("orderId") Integer orderId, @Param("status") String status); // Simplified
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ package com.grtsinry43.bookmanagement.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.grtsinry43.bookmanagement.entity.Publisher;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@ -11,6 +12,7 @@ import com.grtsinry43.bookmanagement.entity.Publisher;
|
||||
* @author grtsinry43
|
||||
* @since 2025-05-19
|
||||
*/
|
||||
@Mapper
|
||||
public interface PublisherMapper extends BaseMapper<Publisher> {
|
||||
|
||||
}
|
||||
|
||||
@ -2,15 +2,34 @@ package com.grtsinry43.bookmanagement.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.grtsinry43.bookmanagement.entity.Reader;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Mapper 接口
|
||||
* Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author grtsinry43
|
||||
* @since 2025-05-19
|
||||
*/
|
||||
public interface ReaderMapper extends BaseMapper<Reader> {
|
||||
@Mapper
|
||||
public interface ReaderMapper extends BaseMapper<Reader> { // 移除了 BaseMapper<Reader>
|
||||
Reader findById(@Param("readerId") Integer readerId);
|
||||
|
||||
Reader findByUsername(@Param("username") String username);
|
||||
|
||||
List<Reader> findAll();
|
||||
|
||||
int insert(Reader reader);
|
||||
|
||||
int updateReaderAdminStatus(@Param("readerId") Integer readerId, @Param("isAdmin") boolean isAdmin);
|
||||
|
||||
int updateReaderBanStatus(@Param("readerId") Integer readerId, @Param("isBanned") boolean isBanned);
|
||||
|
||||
// update and delete methods can be added if needed for admin functionality
|
||||
// 例如: int update(Reader reader); (如果需要更新Reader所有信息)
|
||||
// 例如: int deleteById(@Param("readerId") Integer readerId);
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
package com.grtsinry43.bookmanagement.service;
|
||||
|
||||
import com.grtsinry43.bookmanagement.entity.Book;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@ -11,6 +11,20 @@ import com.baomidou.mybatisplus.extension.service.IService;
|
||||
* @author grtsinry43
|
||||
* @since 2025-05-19
|
||||
*/
|
||||
public interface BookService extends IService<Book> {
|
||||
public interface BookService {
|
||||
Book getBookById(Integer bookId);
|
||||
|
||||
List<Book> getAllBooks();
|
||||
|
||||
List<Book> getBooksByTitle(String title);
|
||||
|
||||
List<Book> getBooksByAuthor(String authorName);
|
||||
|
||||
List<Book> getBooksByPublisher(String publisherName);
|
||||
|
||||
void addBook(Book book);
|
||||
|
||||
void updateBook(Book book);
|
||||
|
||||
void deleteBook(Integer bookId);
|
||||
}
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
package com.grtsinry43.bookmanagement.service;
|
||||
|
||||
import com.grtsinry43.bookmanagement.entity.Orders;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.grtsinry43.bookmanagement.entity.OrderItem;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@ -11,6 +13,14 @@ import com.baomidou.mybatisplus.extension.service.IService;
|
||||
* @author grtsinry43
|
||||
* @since 2025-05-19
|
||||
*/
|
||||
public interface OrdersService extends IService<Orders> {
|
||||
public interface OrdersService {
|
||||
Orders getOrderById(Integer orderId);
|
||||
|
||||
List<Orders> getAllOrders(); // For admin
|
||||
|
||||
List<Orders> getOrdersByReaderId(Integer readerId);
|
||||
|
||||
Orders createOrder(Orders order, List<OrderItem> items); // Simplified: pass items directly
|
||||
|
||||
void updateOrderStatus(Integer orderId, String status); // Simplified
|
||||
}
|
||||
|
||||
@ -1,16 +1,71 @@
|
||||
package com.grtsinry43.bookmanagement.service;
|
||||
|
||||
import com.grtsinry43.bookmanagement.entity.Reader;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.grtsinry43.bookmanagement.vo.ReaderVO; // 导入ReaderVO
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 服务类
|
||||
* 读者服务类接口
|
||||
* </p>
|
||||
*
|
||||
* @author grtsinry43
|
||||
* @since 2025-05-19
|
||||
*/
|
||||
public interface ReaderService extends IService<Reader> {
|
||||
public interface ReaderService {
|
||||
/**
|
||||
* 根据ID获取读者信息 (通常返回实体,Controller层转换为VO)
|
||||
* @param readerId 读者ID
|
||||
* @return 读者实体
|
||||
*/
|
||||
Reader getReaderById(Integer readerId);
|
||||
|
||||
/**
|
||||
* 根据用户名获取读者信息 (通常返回实体)
|
||||
* @param username 用户名
|
||||
* @return 读者实体
|
||||
*/
|
||||
Reader getReaderByUsername(String username);
|
||||
|
||||
/**
|
||||
* 获取所有读者列表 (通常返回实体列表,Controller层转换为VO列表)
|
||||
* @return 读者实体列表
|
||||
*/
|
||||
List<Reader> getAllReaders();
|
||||
|
||||
/**
|
||||
* 注册新读者
|
||||
* @param reader 读者实体 (密码应在服务层处理哈希)
|
||||
*/
|
||||
void registerReader(Reader reader);
|
||||
|
||||
/**
|
||||
* 更新用户管理员状态 (管理员操作)
|
||||
* @param readerId 用户ID
|
||||
* @param isAdmin 是否为管理员
|
||||
*/
|
||||
void updateUserAdminStatus(Integer readerId, boolean isAdmin);
|
||||
|
||||
/**
|
||||
* 更新用户封禁状态 (管理员操作)
|
||||
* @param readerId 用户ID
|
||||
* @param isBanned 是否被封禁
|
||||
*/
|
||||
void updateUserBanStatus(Integer readerId, boolean isBanned);
|
||||
|
||||
/**
|
||||
* 检查用户是否被封禁 (用于登录或权限校验)
|
||||
* @param readerId 用户ID
|
||||
* @return true 如果被封禁, false otherwise
|
||||
*/
|
||||
boolean isUserBanned(Integer readerId); // 参数类型改为Integer
|
||||
|
||||
/**
|
||||
* 用户登录
|
||||
* @param username 用户名
|
||||
* @param password 密码
|
||||
* @return 登录成功后的用户实体,如果登录失败则抛出 BusinessException
|
||||
*/
|
||||
Reader login(String username, String password);
|
||||
}
|
||||
|
||||
@ -1,11 +1,14 @@
|
||||
package com.grtsinry43.bookmanagement.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.grtsinry43.bookmanagement.entity.Book;
|
||||
import com.grtsinry43.bookmanagement.mapper.BookMapper;
|
||||
import com.grtsinry43.bookmanagement.service.BookService;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 服务实现类
|
||||
@ -17,4 +20,46 @@ import org.springframework.stereotype.Service;
|
||||
@Service
|
||||
public class BookServiceImpl extends ServiceImpl<BookMapper, Book> implements BookService {
|
||||
|
||||
@Autowired
|
||||
private BookMapper bookMapper;
|
||||
|
||||
@Override
|
||||
public Book getBookById(Integer bookId) {
|
||||
return bookMapper.findById(bookId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Book> getAllBooks() {
|
||||
return bookMapper.findAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Book> getBooksByTitle(String title) {
|
||||
return bookMapper.findByTitle(title);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Book> getBooksByAuthor(String authorName) {
|
||||
return bookMapper.findByAuthor(authorName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Book> getBooksByPublisher(String publisherName) {
|
||||
return bookMapper.findByPublisher(publisherName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBook(Book book) {
|
||||
bookMapper.insert(book);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBook(Book book) {
|
||||
bookMapper.update(book);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteBook(Integer bookId) {
|
||||
bookMapper.delete(bookId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,10 +1,20 @@
|
||||
package com.grtsinry43.bookmanagement.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.grtsinry43.bookmanagement.entity.Book;
|
||||
import com.grtsinry43.bookmanagement.entity.OrderItem;
|
||||
import com.grtsinry43.bookmanagement.entity.Orders;
|
||||
import com.grtsinry43.bookmanagement.mapper.BookMapper;
|
||||
import com.grtsinry43.bookmanagement.mapper.OrderItemMapper;
|
||||
import com.grtsinry43.bookmanagement.mapper.OrdersMapper;
|
||||
import com.grtsinry43.bookmanagement.service.OrdersService;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@ -15,6 +25,64 @@ import org.springframework.stereotype.Service;
|
||||
* @since 2025-05-19
|
||||
*/
|
||||
@Service
|
||||
public class OrdersServiceImpl extends ServiceImpl<OrdersMapper, Orders> implements OrdersService {
|
||||
public class OrdersServiceImpl extends ServiceImpl<OrdersMapper,Orders> implements OrdersService {
|
||||
|
||||
@Autowired
|
||||
private OrdersMapper ordersMapper;
|
||||
|
||||
@Autowired
|
||||
private OrderItemMapper orderItemMapper;
|
||||
|
||||
@Autowired
|
||||
private BookMapper bookMapper; // To update stock and get price
|
||||
|
||||
@Override
|
||||
public Orders getOrderById(Integer orderId) {
|
||||
return ordersMapper.findById(orderId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Orders> getAllOrders() {
|
||||
return ordersMapper.findAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Orders> getOrdersByReaderId(Integer readerId) {
|
||||
return ordersMapper.findByReaderId(readerId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional // Ensure atomicity
|
||||
public Orders createOrder(Orders order, List<OrderItem> items) {
|
||||
order.setOrderDate(LocalDateTime.now());
|
||||
order.setStatus("PENDING");
|
||||
|
||||
BigDecimal totalAmount = BigDecimal.ZERO;
|
||||
for (OrderItem item : items) {
|
||||
Book book = bookMapper.findById(item.getBookId());
|
||||
if (book == null || book.getStock() < item.getQuantity()) {
|
||||
throw new RuntimeException("Book not found or insufficient stock for: " + (book != null ? book.getTitle() : item.getBookId()));
|
||||
}
|
||||
item.setUnitPrice(book.getPrice());
|
||||
totalAmount = totalAmount.add(book.getPrice().multiply(BigDecimal.valueOf(item.getQuantity())));
|
||||
}
|
||||
order.setTotalAmount(totalAmount);
|
||||
|
||||
ordersMapper.insert(order);
|
||||
|
||||
for (OrderItem item : items) {
|
||||
item.setOrderId(order.getOrderId());
|
||||
orderItemMapper.insert(item);
|
||||
|
||||
Book book = bookMapper.findById(item.getBookId());
|
||||
book.setStock(book.getStock() - item.getQuantity());
|
||||
bookMapper.update(book);
|
||||
}
|
||||
return order;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateOrderStatus(Integer orderId, String status) {
|
||||
ordersMapper.updateStatus(orderId, status);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,14 +1,20 @@
|
||||
package com.grtsinry43.bookmanagement.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.grtsinry43.bookmanagement.common.BusinessException;
|
||||
import com.grtsinry43.bookmanagement.common.ErrorCode;
|
||||
import com.grtsinry43.bookmanagement.entity.Reader;
|
||||
import com.grtsinry43.bookmanagement.mapper.ReaderMapper;
|
||||
import com.grtsinry43.bookmanagement.service.ReaderService;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 服务实现类
|
||||
* 读者服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author grtsinry43
|
||||
@ -17,4 +23,93 @@ import org.springframework.stereotype.Service;
|
||||
@Service
|
||||
public class ReaderServiceImpl extends ServiceImpl<ReaderMapper, Reader> implements ReaderService {
|
||||
|
||||
private final ReaderMapper readerMapper;
|
||||
private final BCryptPasswordEncoder passwordEncoder;
|
||||
|
||||
@Autowired
|
||||
public ReaderServiceImpl(ReaderMapper readerMapper) {
|
||||
this.readerMapper = readerMapper;
|
||||
this.passwordEncoder = new BCryptPasswordEncoder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Reader getReaderById(Integer readerId) {
|
||||
if (readerId == null) {
|
||||
return null;
|
||||
}
|
||||
return readerMapper.findById(readerId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Reader getReaderByUsername(String username) {
|
||||
if (username == null || username.trim().isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return readerMapper.findByUsername(username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Reader> getAllReaders() {
|
||||
return readerMapper.findAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerReader(Reader reader) {
|
||||
if (reader == null || reader.getUsername() == null || reader.getPassword() == null) {
|
||||
throw new BusinessException(ErrorCode.PARAMS_ERROR);
|
||||
}
|
||||
if (readerMapper.findByUsername(reader.getUsername()) != null) {
|
||||
throw new BusinessException(ErrorCode.PARAMS_ERROR);
|
||||
}
|
||||
reader.setPassword(passwordEncoder.encode(reader.getPassword()));
|
||||
readerMapper.insert(reader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateUserAdminStatus(Integer readerId, boolean isAdmin) {
|
||||
Reader reader = readerMapper.findById(readerId);
|
||||
if (reader == null) {
|
||||
throw new BusinessException(ErrorCode.NOT_FOUND);
|
||||
}
|
||||
readerMapper.updateReaderAdminStatus(readerId, isAdmin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateUserBanStatus(Integer readerId, boolean isBanned) {
|
||||
Reader reader = readerMapper.findById(readerId);
|
||||
if (reader == null) {
|
||||
throw new BusinessException(ErrorCode.NOT_FOUND);
|
||||
}
|
||||
readerMapper.updateReaderBanStatus(readerId, isBanned);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUserBanned(Integer readerId) {
|
||||
if (readerId == null) {
|
||||
throw new BusinessException(ErrorCode.PARAMS_ERROR);
|
||||
}
|
||||
Reader reader = readerMapper.findById(readerId);
|
||||
if (reader == null) {
|
||||
throw new BusinessException(ErrorCode.NOT_FOUND);
|
||||
}
|
||||
return reader.getIsBanned() != null && reader.getIsBanned();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Reader login(String username, String password) {
|
||||
if (username == null || username.trim().isEmpty() || password == null || password.isEmpty()) {
|
||||
throw new BusinessException(ErrorCode.PARAMS_ERROR);
|
||||
}
|
||||
Reader reader = readerMapper.findByUsername(username);
|
||||
if (reader == null) {
|
||||
throw new BusinessException(ErrorCode.NOT_FOUND);
|
||||
}
|
||||
if (!passwordEncoder.matches(password, reader.getPassword())) {
|
||||
throw new BusinessException(ErrorCode.PARAMS_ERROR);
|
||||
}
|
||||
if (reader.getIsBanned() != null && reader.getIsBanned()) {
|
||||
throw new BusinessException(ErrorCode.UNAUTHORIZED);
|
||||
}
|
||||
return reader;
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,69 @@
|
||||
package com.grtsinry43.bookmanagement.util;
|
||||
|
||||
import com.auth0.jwt.JWT;
|
||||
import com.auth0.jwt.algorithms.Algorithm;
|
||||
import com.auth0.jwt.exceptions.JWTDecodeException;
|
||||
import com.auth0.jwt.interfaces.DecodedJWT;
|
||||
import com.auth0.jwt.interfaces.JWTVerifier;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author grtsinry43
|
||||
* @date 2024/8/11 21:23
|
||||
* @description 少年负壮气,奋烈自有时!
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class JwtUtil {
|
||||
|
||||
private static String SECRET_KEY;
|
||||
|
||||
@Value("${com.grtsinry43.secret_key}")
|
||||
public void setSecretKey(String secretKey) {
|
||||
SECRET_KEY = secretKey;
|
||||
}
|
||||
|
||||
public static final long EXPIRATION_TIME = 86400000; // 1 day
|
||||
public static final long REFRESH_EXPIRATION_TIME = 2592000000L; // 30 days
|
||||
|
||||
public static String generateToken(String userid) {
|
||||
log.info(SECRET_KEY);
|
||||
Algorithm algorithm = Algorithm.HMAC512(SECRET_KEY);
|
||||
return JWT.create()
|
||||
.withSubject(userid)
|
||||
.withExpiresAt(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
|
||||
.sign(algorithm);
|
||||
}
|
||||
|
||||
public static String generateRefreshToken(String userid) {
|
||||
Algorithm algorithm = Algorithm.HMAC512(SECRET_KEY);
|
||||
return JWT.create()
|
||||
.withSubject(userid)
|
||||
.withExpiresAt(new Date(System.currentTimeMillis() + REFRESH_EXPIRATION_TIME))
|
||||
.sign(algorithm);
|
||||
}
|
||||
|
||||
public static DecodedJWT getDecodedJWT(String token) {
|
||||
try {
|
||||
log.info("Decoding token: {}", token);
|
||||
Algorithm algorithm = Algorithm.HMAC512(SECRET_KEY);
|
||||
JWTVerifier verifier = JWT.require(algorithm).build();
|
||||
return verifier.verify(token);
|
||||
} catch (JWTDecodeException e) {
|
||||
log.error("Invalid token: {}", token, e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isTokenExpired(String token) {
|
||||
return getDecodedJWT(token).getExpiresAt().before(new Date());
|
||||
}
|
||||
|
||||
public static String getUserFromToken(String token) {
|
||||
return getDecodedJWT(token).getSubject();
|
||||
}
|
||||
}
|
||||
78
src/main/java/com/grtsinry43/bookmanagement/vo/ReaderVO.java
Normal file
78
src/main/java/com/grtsinry43/bookmanagement/vo/ReaderVO.java
Normal file
@ -0,0 +1,78 @@
|
||||
package com.grtsinry43.bookmanagement.vo;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 读者视图对象 (安全)
|
||||
*/
|
||||
public class ReaderVO implements Serializable {
|
||||
private Integer readerId;
|
||||
private String username;
|
||||
private String email;
|
||||
private String phone;
|
||||
private Boolean isAdmin;
|
||||
private Boolean isBanned; // 添加是否被封禁字段
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
// 构造函数、Getters 和 Setters
|
||||
public ReaderVO() {
|
||||
}
|
||||
|
||||
public ReaderVO(Integer readerId, String username, String email, String phone, Boolean isAdmin, Boolean isBanned) {
|
||||
this.readerId = readerId;
|
||||
this.username = username;
|
||||
this.email = email;
|
||||
this.phone = phone;
|
||||
this.isAdmin = isAdmin;
|
||||
this.isBanned = isBanned;
|
||||
}
|
||||
|
||||
public Integer getReaderId() {
|
||||
return readerId;
|
||||
}
|
||||
|
||||
public void setReaderId(Integer readerId) {
|
||||
this.readerId = readerId;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public String getPhone() {
|
||||
return phone;
|
||||
}
|
||||
|
||||
public void setPhone(String phone) {
|
||||
this.phone = phone;
|
||||
}
|
||||
|
||||
public Boolean getIsAdmin() {
|
||||
return isAdmin;
|
||||
}
|
||||
|
||||
public void setIsAdmin(Boolean admin) {
|
||||
isAdmin = admin;
|
||||
}
|
||||
|
||||
public Boolean getIsBanned() {
|
||||
return isBanned;
|
||||
}
|
||||
|
||||
public void setIsBanned(Boolean banned) {
|
||||
isBanned = banned;
|
||||
}
|
||||
}
|
||||
@ -6,4 +6,8 @@ spring.datasource.driver-class-name=org.postgresql.Driver
|
||||
# log file configuration
|
||||
logging.config=classpath:logback-spring.xml
|
||||
server.shutdown=graceful
|
||||
server.port=8080
|
||||
server.port=8080
|
||||
|
||||
mybatis.type-aliases-package=com.grtsinry43.bookmanagement.entity
|
||||
mybatis.configuration.map-underscore-to-camel-case=true
|
||||
logging.level.com.grtsinry43.bookmanagement.mapper=DEBUG
|
||||
|
||||
49
src/main/resources/mapper/BookMapper.xml
Normal file
49
src/main/resources/mapper/BookMapper.xml
Normal file
@ -0,0 +1,49 @@
|
||||
<?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.grtsinry43.bookmanagement.mapper.BookMapper">
|
||||
|
||||
<select id="findById" resultType="com.grtsinry43.bookmanagement.entity.Book">
|
||||
SELECT * FROM book WHERE book_id = #{bookId}
|
||||
</select>
|
||||
|
||||
<select id="findAll" resultType="com.grtsinry43.bookmanagement.entity.Book">
|
||||
SELECT * FROM book
|
||||
</select>
|
||||
|
||||
<select id="findByTitle" resultType="com.grtsinry43.bookmanagement.entity.Book">
|
||||
SELECT * FROM book WHERE title LIKE CONCAT('%', #{title}, '%')
|
||||
</select>
|
||||
|
||||
<select id="findByAuthor" resultType="com.grtsinry43.bookmanagement.entity.Book">
|
||||
SELECT b.* FROM book b
|
||||
JOIN book_author ba ON b.book_id = ba.book_id
|
||||
JOIN author a ON ba.author_id = a.author_id
|
||||
WHERE a.name LIKE CONCAT('%', #{authorName}, '%')
|
||||
</select>
|
||||
|
||||
<select id="findByPublisher" resultType="com.grtsinry43.bookmanagement.entity.Book">
|
||||
SELECT b.* FROM book b
|
||||
JOIN publisher p ON b.publisher_id = p.publisher_id
|
||||
WHERE p.name LIKE CONCAT('%', #{publisherName}, '%')
|
||||
</select>
|
||||
|
||||
<insert id="insert" parameterType="com.grtsinry43.bookmanagement.entity.Book" useGeneratedKeys="true" keyProperty="bookId">
|
||||
INSERT INTO book (title, isbn, price, stock, publish_date, publisher_id)
|
||||
VALUES (#{title}, #{isbn}, #{price}, #{stock}, #{publishDate}, #{publisherId})
|
||||
</insert>
|
||||
|
||||
<update id="update" parameterType="com.grtsinry43.bookmanagement.entity.Book">
|
||||
UPDATE book
|
||||
SET title = #{title},
|
||||
isbn = #{isbn},
|
||||
price = #{price},
|
||||
stock = #{stock},
|
||||
publish_date = #{publishDate},
|
||||
publisher_id = #{publisherId}
|
||||
WHERE book_id = #{bookId}
|
||||
</update>
|
||||
|
||||
<delete id="delete">
|
||||
DELETE FROM book WHERE book_id = #{bookId}
|
||||
</delete>
|
||||
</mapper>
|
||||
24
src/main/resources/mapper/OrderItemMapper.xml
Normal file
24
src/main/resources/mapper/OrderItemMapper.xml
Normal file
@ -0,0 +1,24 @@
|
||||
<?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.grtsinry43.bookmanagement.mapper.OrderItemMapper">
|
||||
|
||||
<select id="findByOrderId" resultType="com.grtsinry43.bookmanagement.entity.OrderItem">
|
||||
SELECT * FROM order_item WHERE order_id = #{orderId}
|
||||
</select>
|
||||
|
||||
<insert id="insert" parameterType="com.grtsinry43.bookmanagement.entity.OrderItem" useGeneratedKeys="true" keyProperty="orderItemId">
|
||||
INSERT INTO order_item (order_id, book_id, quantity, unit_price)
|
||||
VALUES (#{orderId}, #{bookId}, #{quantity}, #{unitPrice})
|
||||
</insert>
|
||||
|
||||
<!-- Example for batch insert -->
|
||||
<!--
|
||||
<insert id="insertBatch" parameterType="java.util.List">
|
||||
INSERT INTO order_item (order_id, book_id, quantity, unit_price) VALUES
|
||||
<foreach collection="list" item="item" separator=",">
|
||||
(#{item.orderId}, #{item.bookId}, #{item.quantity}, #{item.unitPrice})
|
||||
</foreach>
|
||||
</insert>
|
||||
-->
|
||||
|
||||
</mapper>
|
||||
26
src/main/resources/mapper/OrdersMapper.xml
Normal file
26
src/main/resources/mapper/OrdersMapper.xml
Normal file
@ -0,0 +1,26 @@
|
||||
<?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.grtsinry43.bookmanagement.mapper.OrdersMapper">
|
||||
|
||||
<select id="findById" resultType="com.grtsinry43.bookmanagement.entity.Orders">
|
||||
SELECT * FROM orders WHERE order_id = #{orderId}
|
||||
</select>
|
||||
|
||||
<select id="findAll" resultType="com.grtsinry43.bookmanagement.entity.Orders">
|
||||
SELECT * FROM orders ORDER BY order_date DESC
|
||||
</select>
|
||||
|
||||
<select id="findByReaderId" resultType="com.grtsinry43.bookmanagement.entity.Orders">
|
||||
SELECT * FROM orders WHERE reader_id = #{readerId} ORDER BY order_date DESC
|
||||
</select>
|
||||
|
||||
<insert id="insert" parameterType="com.grtsinry43.bookmanagement.entity.Orders" useGeneratedKeys="true" keyProperty="orderId">
|
||||
INSERT INTO orders (reader_id, order_date, total_amount, status)
|
||||
VALUES (#{readerId}, #{orderDate}, #{totalAmount}, #{status})
|
||||
</insert>
|
||||
|
||||
<update id="updateStatus">
|
||||
UPDATE orders SET status = #{status} WHERE order_id = #{orderId}
|
||||
</update>
|
||||
|
||||
</mapper>
|
||||
30
src/main/resources/mapper/ReaderMapper.xml
Normal file
30
src/main/resources/mapper/ReaderMapper.xml
Normal file
@ -0,0 +1,30 @@
|
||||
<?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.grtsinry43.bookmanagement.mapper.ReaderMapper">
|
||||
|
||||
<select id="findById" resultType="com.grtsinry43.bookmanagement.entity.Reader">
|
||||
SELECT * FROM reader WHERE reader_id = #{readerId}
|
||||
</select>
|
||||
|
||||
<select id="findByUsername" resultType="com.grtsinry43.bookmanagement.entity.Reader">
|
||||
SELECT * FROM reader WHERE username = #{username}
|
||||
</select>
|
||||
|
||||
<select id="findAll" resultType="com.grtsinry43.bookmanagement.entity.Reader">
|
||||
SELECT * FROM reader
|
||||
</select>
|
||||
|
||||
<insert id="insert" parameterType="com.grtsinry43.bookmanagement.entity.Reader" useGeneratedKeys="true" keyProperty="readerId">
|
||||
INSERT INTO reader (username, password, email, phone, is_admin, is_banned)
|
||||
VALUES (#{username}, #{password}, #{email}, #{phone}, #{isAdmin,jdbcType=BOOLEAN}, #{isBanned,jdbcType=BOOLEAN})
|
||||
</insert>
|
||||
|
||||
<update id="updateReaderAdminStatus">
|
||||
UPDATE reader SET is_admin = #{isAdmin} WHERE reader_id = #{readerId}
|
||||
</update>
|
||||
|
||||
<update id="updateReaderBanStatus">
|
||||
UPDATE reader SET is_banned = #{isBanned} WHERE reader_id = #{readerId}
|
||||
</update>
|
||||
|
||||
</mapper>
|
||||
@ -47,6 +47,8 @@ CREATE TABLE reader
|
||||
username VARCHAR(50) NOT NULL UNIQUE,
|
||||
password VARCHAR(100) NOT NULL,
|
||||
email VARCHAR(100) NOT NULL UNIQUE,
|
||||
is_admin BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
is_banned BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
phone VARCHAR(20)
|
||||
);
|
||||
|
||||
|
||||
@ -1,5 +0,0 @@
|
||||
<?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.grtsinry43.bookmanagement.mapper.BookMapper">
|
||||
|
||||
</mapper>
|
||||
@ -1,5 +0,0 @@
|
||||
<?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.grtsinry43.bookmanagement.mapper.OrderItemMapper">
|
||||
|
||||
</mapper>
|
||||
@ -1,5 +0,0 @@
|
||||
<?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.grtsinry43.bookmanagement.mapper.OrdersMapper">
|
||||
|
||||
</mapper>
|
||||
@ -1,5 +0,0 @@
|
||||
<?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.grtsinry43.bookmanagement.mapper.ReaderMapper">
|
||||
|
||||
</mapper>
|
||||
Loading…
x
Reference in New Issue
Block a user