本例子的依赖
要实现的内容
通过get 、post 、put 和delete 接口,对数据库中的trade.categories表进行增删改查操作。
目录结构
c
com.test/
│
├── controller/
│ ├── CateController.java
│
├── pojo/
│ ├── dto/
│ │ └── CategoryDto.java
│ ├── Category.java
│ └── ResponseMessage.java
│
├── repository/
│ └── CateRepository.java
│
└── service/
├── CateRepository.java
└── ICateRepository.java
各目录文件之间的关系(仅限于本文章)
添加配置
java
/* application.properties */
spring.datasource.url=jdbc:mysql://localhost:3306/trade
spring.datasource.username=root
#spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
当设置为 true 时,Hibernate 会在控制台中打印所有执行的 SQL 语句,方便调试和查看 SQL 查询。
spring.jpa.properties.hibernate.format_sql=true
当设置为 true 时,Hibernate 会将 SQL 语句格式化成更具可读性的形式便于阅读。
spring.jpa.hibernate.ddl-auto=update
值 | 作用 |
---|---|
update | 如不存在表则创建新表,已有表会尝试修改 |
create | 启动时先删除表,再重新创建表 |
create-drop | 应用停止时会删除表 |
none | 不会对数据库结构进行任何操作 |
映射categories表
java
/* Category.java */
@Table(name = "categories")
@Entity
public class Category {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "category_id")
private Integer categoryID;
@Column(name = "category_name")
private String categoryName;
@Column(name = "description")
private String description;
}
/* ...省略 get set方法 */
@Table(name = "categories")
Category 类将与数据库中名为 categories 的表进行映射。
@Entity
注解标记该类为一个 JPA 实体,即一个可以映射到数据库表的类。JPA 会在运行时使用该类与数据库进行交互。
@Id
标识该字段是实体的主键。
@GeneratedValue
注解表示主键值是自动生成的。strategy = GenerationType.IDENTITY 表示数据库会为该字段生成唯一的自增值。也就是说,每次插入一条新记录时,categoryID 会自动递增。
@Column
注解用来指定该字段映射到数据库表中的哪一列。
dto传输类
java
/* CategoryDto.java */
public class CategoryDto {
private Integer categoryID;
@NotBlank(message = "分类名称不能为空")
private String categoryName;
@NotBlank(message = "分类描述不能为空")
private String description;
}
/* ...省略 get set方法 */
由于主键id是自动生成的,所以插入值时只用到两个列。
API响应数据类
java
/* ResponseMessage.java */
public class ResponseMessage<T> {
private Integer code;
private String message;
private T data;
public ResponseMessage(Integer code, String message, T data) {
this.code = code;
this.message = message;
this.data = data;
}
public static <T> ResponseMessage<T> success(T data){
return new ResponseMessage<>(HttpStatus.OK.value(),"success!",data);
}
/* ...省略 get set方法 */
}
定义了一个泛型类 ,用于封装统一格式的响应消息,里面有一个静态泛型方法,成功响应返回状态码、字符串和对象内容。
统一类型返回
java
/* GlobalExceptionHandlerAdvice.java */
@RestControllerAdvice
public class GlobalExceptionHandlerAdvice {
Logger log = LoggerFactory.getLogger(GlobalExceptionHandlerAdvice.class);
@ExceptionHandler({Exception.class})
public ResponseMessage handlerException(Exception e, HttpServletRequest request, HttpServletResponse response){
log.error("统一异常:",e);
return new ResponseMessage(500,"error",null);
}
}
这个类用来处理全局范围内的异常,响应报异常返回统一的消息。
@RestControllerAdvice
通过该注解,可以捕获所有控制器中的异常,并返回统一格式的 JSON 响应。
@ExceptionHandler
声明该方法用于处理指定的异常类型,{Exception.class}:捕获所有 Exception 类型的异常,包括其子类。
POST
CateRepository 继承 了 Spring Data JPA 提供的 CrudRepository 接口,可以获得基本的CRUD 操作(如增、删、改、查)。
java
/* CateRepository.java */
@Repository
public interface CateRepository extends CrudRepository<Category,Integer> {
}
在服务类添加add方法,插入请求body里的内容。
java
/* ICateService.java 服务接口 */
public interface ICateService {
/**
* 插入分类
* @param categoryDto
*/
Category add(CategoryDto categoryDto);
}
java
/* CateService.java 实现服务接口 */
@Service
public class CateService implements ICateService{
@Autowired
CateRepository cateRepository;
@Override
public Category add(CategoryDto categoryDto) {
Category category = new Category();
BeanUtils.copyProperties(categoryDto,category);
return cateRepository.save(category);
}
}
@Service
表示该类是一个专门用于 Service 层 的注解,用于处理业务逻辑 ,Spring 会自动检测并注册 CateService 为一个 Spring Bean,因此可以被其他类注入和使用。
@Autowired
Spring 提供的依赖注入注解 ,它用于自动注入依赖的对象。Spring 容器会自动将 CateRepository 的实例注入到 CateService 类中,cateRepository 便可以用来执行数据库操作,如保存、查询、删除类别等。
BeanUtils.copyProperties(first,second)
此方法会自动匹配相同名字的字段和兼容的类型,将 first对象中的数据赋值到second对象中。
接下来写Controller 对象的里的内容,完成post处理接口。
java
/* Controller.java */
@RestController
@RequestMapping("/cate")
public class CateController {
@Autowired
ICateService cateService;
@PostMapping
public ResponseMessage<Category> add(@Validated @RequestBody CategoryDto categoryDto){
Category cateNew = cateService.add(categoryDto);
return ResponseMessage.success(cateNew);
}
}
@RestController
该注解使得 CateController 类成为一个 RESTful风格的控制器,可以处理 HTTP 请求,并返回 JSON 数据。
@RequestMapping("/cate")
该注解用于定义该控制器处理的请求 URL 路径前缀。
@PostMapping
当收到 POST 请求时,该方法会被调用。add 方法接收前端提交的 CategoryDto 数据 ,并通过 cateService 保存数据。返回的结果是一个封装了状态、消息和数据的统一响应对象 ResponseMessage,以 JSON 格式返回给客户端。
GET 通过id查询分类
java
/* Controller.java */
@GetMapping("/{id}")
public ResponseMessage<Category> get(@PathVariable Integer id){
return ResponseMessage.success(cateService.getCate(id));
}
java
/* ICateService.java 服务接口 */
/**
* 查询分类
* @param id
*/
Category getCate(Integer id);
java
/* CateService.java 实现服务接口 */
@Override
public Category getCate(Integer id) {
return cateRepository.findById(id).orElseThrow(()-> new IllegalArgumentException("分类不存在"));
}
PUT 通过id修改分类
java
/* Controller.java */
@PutMapping
public ResponseMessage<Category> update(@Validated @RequestBody CategoryDto categoryDto){
Category cateNew = cateService.cateEdit(categoryDto);
return ResponseMessage.success(cateNew);
}
java
/* ICateService.java 服务接口 */
/**
* 编辑分类
* @param categoryDto
*/
Category cateEdit(CategoryDto categoryDto);
java
/* CateService.java 实现服务接口 */
@Override
public Category cateEdit(CategoryDto categoryDto) {
Category category = new Category();
BeanUtils.copyProperties(categoryDto,category);
return cateRepository.save(category);
}
Delete 通过id删除数据
java
/* Controller.java */
@DeleteMapping("/{id}")
public ResponseMessage<Category> delete(@PathVariable Integer id){
cateService.cateDelete(id);
return ResponseMessage.success(null);
}
java
/* ICateService.java 服务接口 */
/**
* 删除分类
*
* @param id
*/
void cateDelete(Integer id);
java
/* CateService.java 实现服务接口 */
@Override
public void cateDelete(Integer id) {
cateRepository.deleteById(id);
}