feat(分类模块): 实现分类管理功能
新增分类模块相关代码,包括实体类、DTO、Repository、Service和Controller 添加分类数据初始化逻辑和日志记录 实现分类的增删改查及搜索功能
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
package com.qf.myafterprojecy.controller;
|
||||
|
||||
import com.qf.myafterprojecy.pojo.Category;
|
||||
import com.qf.myafterprojecy.pojo.ResponseMessage;
|
||||
import com.qf.myafterprojecy.pojo.dto.CategoryDto;
|
||||
import com.qf.myafterprojecy.service.ICategoryService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分类控制器类,处理分类相关的HTTP请求
|
||||
* 提供分类的增删改查功能
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/categories")
|
||||
@Validated
|
||||
public class CategoryController {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(CategoryController.class);
|
||||
|
||||
@Autowired
|
||||
private ICategoryService categoryService;
|
||||
|
||||
/**
|
||||
* 根据ID获取分类信息
|
||||
* @param id 分类ID
|
||||
* @return 返回分类信息
|
||||
*/
|
||||
@GetMapping("/{id}")
|
||||
public ResponseMessage<Category> getCategoryById(@PathVariable Integer id) {
|
||||
log.info("接收根据ID获取分类的请求: {}", id);
|
||||
return categoryService.getCategoryById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有分类列表
|
||||
* @return 返回分类列表
|
||||
*/
|
||||
@GetMapping
|
||||
public ResponseMessage<List<Category>> getAllCategories() {
|
||||
log.info("接收获取所有分类列表的请求");
|
||||
return categoryService.getAllCategories();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建新分类
|
||||
* @param categoryDto 分类数据传输对象
|
||||
* @return 返回创建结果
|
||||
*/
|
||||
@PostMapping
|
||||
public ResponseMessage<Category> createCategory(@Valid @RequestBody CategoryDto categoryDto) {
|
||||
log.info("接收创建分类的请求: {}", categoryDto.getTypename());
|
||||
return categoryService.saveCategory(categoryDto);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新分类信息
|
||||
* @param id 分类ID
|
||||
* @param categoryDto 分类数据传输对象
|
||||
* @return 返回更新结果
|
||||
*/
|
||||
@PutMapping("/{id}")
|
||||
public ResponseMessage<Category> updateCategory(
|
||||
@PathVariable Integer id,
|
||||
@Valid @RequestBody CategoryDto categoryDto) {
|
||||
log.info("接收更新分类的请求: ID={}, 分类名称={}", id, categoryDto.getTypename());
|
||||
return categoryService.updateCategory(id, categoryDto);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除分类
|
||||
* @param id 分类ID
|
||||
* @return 返回删除结果
|
||||
*/
|
||||
@DeleteMapping("/{id}")
|
||||
public ResponseMessage<Boolean> deleteCategory(@PathVariable Integer id) {
|
||||
log.info("接收删除分类的请求: {}", id);
|
||||
return categoryService.deleteCategory(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据分类名称搜索分类
|
||||
* @param typename 分类名称
|
||||
* @return 返回符合条件的分类列表
|
||||
*/
|
||||
@GetMapping("/search")
|
||||
public ResponseMessage<List<Category>> searchCategoriesByTypename(@RequestParam String typename) {
|
||||
log.info("接收根据名称搜索分类的请求: {}", typename);
|
||||
return categoryService.searchCategoriesByTypename(typename);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package com.qf.myafterprojecy.init;
|
||||
|
||||
import com.qf.myafterprojecy.pojo.Category;
|
||||
import com.qf.myafterprojecy.repository.CategoryRepository;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.ApplicationArguments;
|
||||
import org.springframework.boot.ApplicationRunner;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分类数据初始化类,用于在应用启动时初始化分类数据
|
||||
*/
|
||||
@Component
|
||||
public class CategoryDataInit implements ApplicationRunner {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(CategoryDataInit.class);
|
||||
|
||||
@Autowired
|
||||
private CategoryRepository categoryRepository;
|
||||
|
||||
@Override
|
||||
public void run(ApplicationArguments args) throws Exception {
|
||||
logger.info("===== 分类数据初始化开始 =====");
|
||||
|
||||
// 检查数据库中是否已有分类数据
|
||||
long count = categoryRepository.count();
|
||||
logger.info("当前数据库中分类数量: {}", count);
|
||||
|
||||
// 如果没有分类数据,添加一些测试数据
|
||||
if (count == 0) {
|
||||
logger.info("数据库中没有分类数据,开始添加初始化数据...");
|
||||
addInitialCategories();
|
||||
} else {
|
||||
logger.info("数据库中已存在分类数据,无需初始化");
|
||||
}
|
||||
|
||||
logger.info("===== 分类数据初始化结束 =====");
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加初始分类数据
|
||||
*/
|
||||
private void addInitialCategories() {
|
||||
List<Category> categories = new ArrayList<>();
|
||||
|
||||
// 创建几个常见的文章分类
|
||||
Category category1 = new Category();
|
||||
category1.setTypename("技术分享");
|
||||
category1.setDescription("技术文章、教程、经验分享等");
|
||||
category1.setCreatedAt(LocalDateTime.now());
|
||||
category1.setUpdatedAt(LocalDateTime.now());
|
||||
categories.add(category1);
|
||||
|
||||
Category category2 = new Category();
|
||||
category2.setTypename("生活随笔");
|
||||
category2.setDescription("日常生活、心情记录、随笔等");
|
||||
category2.setCreatedAt(LocalDateTime.now());
|
||||
category2.setUpdatedAt(LocalDateTime.now());
|
||||
categories.add(category2);
|
||||
|
||||
Category category3 = new Category();
|
||||
category3.setTypename("学习笔记");
|
||||
category3.setDescription("学习过程中的笔记、总结等");
|
||||
category3.setCreatedAt(LocalDateTime.now());
|
||||
category3.setUpdatedAt(LocalDateTime.now());
|
||||
categories.add(category3);
|
||||
|
||||
Category category4 = new Category();
|
||||
category4.setTypename("行业动态");
|
||||
category4.setDescription("行业新闻、趋势分析等");
|
||||
category4.setCreatedAt(LocalDateTime.now());
|
||||
category4.setUpdatedAt(LocalDateTime.now());
|
||||
categories.add(category4);
|
||||
|
||||
// 保存分类数据到数据库
|
||||
categoryRepository.saveAll(categories);
|
||||
logger.info("成功添加 {} 条分类数据", categories.size());
|
||||
}
|
||||
}
|
||||
68
src/main/java/com/qf/myafterprojecy/pojo/Category.java
Normal file
68
src/main/java/com/qf/myafterprojecy/pojo/Category.java
Normal file
@@ -0,0 +1,68 @@
|
||||
package com.qf.myafterprojecy.pojo;
|
||||
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Entity
|
||||
@Table(name = "category")
|
||||
public class Category {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "typeid")
|
||||
private Integer typeid;
|
||||
|
||||
@NotBlank(message = "分类名称不能为空")
|
||||
@Column(name = "typename")
|
||||
private String typename;
|
||||
|
||||
@Column(name = "description")
|
||||
private String description;
|
||||
|
||||
@Column(name = "created_at")
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
@Column(name = "updated_at")
|
||||
private LocalDateTime updatedAt;
|
||||
|
||||
// Getters and Setters
|
||||
public Integer getTypeid() {
|
||||
return typeid;
|
||||
}
|
||||
|
||||
public void setTypeid(Integer typeid) {
|
||||
this.typeid = typeid;
|
||||
}
|
||||
|
||||
public String getTypename() {
|
||||
return typename;
|
||||
}
|
||||
|
||||
public void setTypename(String typename) {
|
||||
this.typename = typename;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public LocalDateTime getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
public void setCreatedAt(LocalDateTime createdAt) {
|
||||
this.createdAt = createdAt;
|
||||
}
|
||||
|
||||
public LocalDateTime getUpdatedAt() {
|
||||
return updatedAt;
|
||||
}
|
||||
|
||||
public void setUpdatedAt(LocalDateTime updatedAt) {
|
||||
this.updatedAt = updatedAt;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.qf.myafterprojecy.pojo.dto;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public class CategoryDto {
|
||||
private Integer typeid;
|
||||
private String typename;
|
||||
private String description;
|
||||
private LocalDateTime createdAt;
|
||||
private LocalDateTime updatedAt;
|
||||
|
||||
// Getters and Setters
|
||||
public Integer getTypeid() {
|
||||
return typeid;
|
||||
}
|
||||
|
||||
public void setTypeid(Integer typeid) {
|
||||
this.typeid = typeid;
|
||||
}
|
||||
|
||||
public String getTypename() {
|
||||
return typename;
|
||||
}
|
||||
|
||||
public void setTypename(String typename) {
|
||||
this.typename = typename;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public LocalDateTime getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
public void setCreatedAt(LocalDateTime createdAt) {
|
||||
this.createdAt = createdAt;
|
||||
}
|
||||
|
||||
public LocalDateTime getUpdatedAt() {
|
||||
return updatedAt;
|
||||
}
|
||||
|
||||
public void setUpdatedAt(LocalDateTime updatedAt) {
|
||||
this.updatedAt = updatedAt;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.qf.myafterprojecy.repository;
|
||||
|
||||
import com.qf.myafterprojecy.pojo.Category;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface CategoryRepository extends JpaRepository<Category, Integer> {
|
||||
|
||||
/**
|
||||
* 根据分类名称查询分类信息
|
||||
* @param typename 分类名称
|
||||
* @return 返回符合条件的分类列表
|
||||
*/
|
||||
List<Category> findByTypenameContaining(String typename);
|
||||
|
||||
/**
|
||||
* 检查分类名称是否存在
|
||||
* @param typename 分类名称
|
||||
* @return 返回是否存在
|
||||
*/
|
||||
boolean existsByTypename(String typename);
|
||||
}
|
||||
141
src/main/java/com/qf/myafterprojecy/service/CategoryService.java
Normal file
141
src/main/java/com/qf/myafterprojecy/service/CategoryService.java
Normal file
@@ -0,0 +1,141 @@
|
||||
package com.qf.myafterprojecy.service;
|
||||
|
||||
import com.qf.myafterprojecy.pojo.Category;
|
||||
import com.qf.myafterprojecy.pojo.ResponseMessage;
|
||||
import com.qf.myafterprojecy.pojo.dto.CategoryDto;
|
||||
import com.qf.myafterprojecy.repository.CategoryRepository;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class CategoryService implements ICategoryService {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(CategoryService.class);
|
||||
|
||||
@Autowired
|
||||
private CategoryRepository categoryRepository;
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public ResponseMessage<Category> getCategoryById(Integer id) {
|
||||
try {
|
||||
if (id == null || id <= 0) {
|
||||
return ResponseMessage.failure("分类ID无效");
|
||||
}
|
||||
Category category = categoryRepository.findById(id)
|
||||
.orElseThrow(() -> new RuntimeException("分类不存在"));
|
||||
return ResponseMessage.success(category);
|
||||
} catch (Exception e) {
|
||||
log.error("获取分类失败: {}", e.getMessage());
|
||||
return ResponseMessage.failure("获取分类失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public ResponseMessage<List<Category>> getAllCategories() {
|
||||
try {
|
||||
List<Category> categories = categoryRepository.findAll();
|
||||
return ResponseMessage.success(categories);
|
||||
} catch (DataAccessException e) {
|
||||
log.error("获取分类列表失败: {}", e.getMessage());
|
||||
return ResponseMessage.failure("获取分类列表失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public ResponseMessage<Category> saveCategory(CategoryDto categoryDto) {
|
||||
try {
|
||||
// 检查分类名称是否已存在
|
||||
if (categoryRepository.existsByTypename(categoryDto.getTypename())) {
|
||||
return ResponseMessage.failure("分类名称已存在");
|
||||
}
|
||||
|
||||
Category category = new Category();
|
||||
BeanUtils.copyProperties(categoryDto, category);
|
||||
category.setCreatedAt(LocalDateTime.now());
|
||||
category.setUpdatedAt(LocalDateTime.now());
|
||||
|
||||
Category savedCategory = categoryRepository.save(category);
|
||||
return ResponseMessage.success(savedCategory);
|
||||
} catch (DataAccessException e) {
|
||||
log.error("保存分类失败: {}", e.getMessage());
|
||||
return ResponseMessage.failure("保存分类失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public ResponseMessage<Category> updateCategory(Integer id, CategoryDto categoryDto) {
|
||||
try {
|
||||
if (id == null || id <= 0) {
|
||||
return ResponseMessage.failure("分类ID无效");
|
||||
}
|
||||
|
||||
Category category = categoryRepository.findById(id)
|
||||
.orElseThrow(() -> new RuntimeException("分类不存在"));
|
||||
|
||||
// 如果修改了分类名称,检查新名称是否已存在
|
||||
if (!category.getTypename().equals(categoryDto.getTypename()) &&
|
||||
categoryRepository.existsByTypename(categoryDto.getTypename())) {
|
||||
return ResponseMessage.failure("分类名称已存在");
|
||||
}
|
||||
|
||||
BeanUtils.copyProperties(categoryDto, category);
|
||||
category.setUpdatedAt(LocalDateTime.now());
|
||||
|
||||
Category updatedCategory = categoryRepository.save(category);
|
||||
return ResponseMessage.success(updatedCategory);
|
||||
} catch (Exception e) {
|
||||
log.error("更新分类失败: {}", e.getMessage());
|
||||
return ResponseMessage.failure("更新分类失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public ResponseMessage<Boolean> deleteCategory(Integer id) {
|
||||
try {
|
||||
if (id == null || id <= 0) {
|
||||
return ResponseMessage.failure("分类ID无效");
|
||||
}
|
||||
|
||||
if (!categoryRepository.existsById(id)) {
|
||||
return ResponseMessage.failure("分类不存在");
|
||||
}
|
||||
|
||||
// 注意:实际项目中可能需要先检查是否有文章引用该分类
|
||||
// 如果有,可能需要先处理文章或者禁止删除
|
||||
categoryRepository.deleteById(id);
|
||||
return ResponseMessage.success(true);
|
||||
} catch (Exception e) {
|
||||
log.error("删除分类失败: {}", e.getMessage());
|
||||
return ResponseMessage.failure("删除分类失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public ResponseMessage<List<Category>> searchCategoriesByTypename(String typename) {
|
||||
try {
|
||||
if (typename == null || typename.trim().isEmpty()) {
|
||||
return ResponseMessage.failure("分类名称不能为空");
|
||||
}
|
||||
|
||||
List<Category> categories = categoryRepository.findByTypenameContaining(typename);
|
||||
return ResponseMessage.success(categories);
|
||||
} catch (DataAccessException e) {
|
||||
log.error("搜索分类失败: {}", e.getMessage());
|
||||
return ResponseMessage.failure("搜索分类失败");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.qf.myafterprojecy.service;
|
||||
|
||||
import com.qf.myafterprojecy.pojo.Category;
|
||||
import com.qf.myafterprojecy.pojo.ResponseMessage;
|
||||
import com.qf.myafterprojecy.pojo.dto.CategoryDto;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ICategoryService {
|
||||
/**
|
||||
* 根据ID获取分类信息
|
||||
* @param id 分类ID
|
||||
* @return 返回分类信息
|
||||
*/
|
||||
ResponseMessage<Category> getCategoryById(Integer id);
|
||||
|
||||
/**
|
||||
* 获取所有分类列表
|
||||
* @return 返回分类列表
|
||||
*/
|
||||
ResponseMessage<List<Category>> getAllCategories();
|
||||
|
||||
/**
|
||||
* 保存新分类
|
||||
* @param categoryDto 分类数据传输对象
|
||||
* @return 返回保存结果
|
||||
*/
|
||||
ResponseMessage<Category> saveCategory(CategoryDto categoryDto);
|
||||
|
||||
/**
|
||||
* 更新分类信息
|
||||
* @param id 分类ID
|
||||
* @param categoryDto 分类数据传输对象
|
||||
* @return 返回更新结果
|
||||
*/
|
||||
ResponseMessage<Category> updateCategory(Integer id, CategoryDto categoryDto);
|
||||
|
||||
/**
|
||||
* 删除分类
|
||||
* @param id 分类ID
|
||||
* @return 返回删除结果
|
||||
*/
|
||||
ResponseMessage<Boolean> deleteCategory(Integer id);
|
||||
|
||||
/**
|
||||
* 根据分类名称搜索分类
|
||||
* @param typename 分类名称
|
||||
* @return 返回符合条件的分类列表
|
||||
*/
|
||||
ResponseMessage<List<Category>> searchCategoriesByTypename(String typename);
|
||||
}
|
||||
Reference in New Issue
Block a user