[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"article-public-mbxrGCSA":3,"public-project-articles-mbxrGCSA":17},{"id":4,"uuid":5,"project_id":6,"title":7,"content":8,"type":9,"status":10,"public_enabled":10,"views":11,"sort":12,"created_at":13,"updated_at":14,"project_title":15,"project_slug":16},1220,"mbxrGCSA",60,"02. 学习SpringBoot4+JPA基本的增删改查接口","这不是噩梦，这是非常友好的提示！这是奖励！！\n\n\u003C!-- 这是一张图片，ocr 内容为：RESPONSE BODY CODE\":\"500\", \"DATA\": NULL, \"MSG\":\"系统繁忙,请稍后再试\" -->\n![](https:\u002F\u002Fcdn.nlark.com\u002Fyuque\u002F0\u002F2026\u002Fpng\u002F751015\u002F1770347340198-4871a702-ce83-4481-a4b4-f84559a62165.png)\n\n\u003C!-- 这是一张图片，ocr 内容为：UT ON G OPI TUYN UMONOMON OOPPOR COPPOR THOUREF OF ONCE JAVA:346) ~[SPRING-TX-7.0.3.JAR ORT.DATAACCESSUTILS.TRANSLATEIFNECESSARY(DATAACCESSUTILS.JA AT ORG.SPRINGFRAMEWORK.DAO.SUPPORT.DATAACC AT ORG-SPRINGFRANEWORK-8OP.FRAMEMORK.REFLECTIYEHETHODINVOCATION.PROCEED(REFLECTIYEHETHODINVOSATION-J7 ~[SPRING AT JDK.PROXY2\u002FJDK.PROXY2.$PROXY137.SAVE(UNKNOWN SOURCE) ~[NA:NAL- AT COM.EXAMPLE.SERVICE.ADMINSERVICE.SAVE(ADMINSERVICE.JAVA:39) -TCLASSES\u002F:NA) \u003C12 INTERNAL LINES> ~[CLASSES\u002F:NA] COM.EXAMPLE.CONTROLLER.ADMINCONTROLLER.SAVE(ADMINCONTROLLER.JAVA:29) AT ~[TOMCAT-EMBED-CORE-11.0.15.JAR:6.1] \u003C1 INTERNAL LING JAKARTA.SERVLET.HTTP.HTTPSERVLET.SERVICE(HTTPSERVLET.JAVA:649) AT 4710) ~[TOMCAT-EMBED-CORE-11.0.15.JAR:6.1] \u003C28 INTERNAL LIN JAKARTA.SERVLET.HTTP.HTTPSERVLET.SERVICE(HTTPSERVLET.JAVA:710) AT JAL ED WORK [TABLE SPRINGBOOT_VU \u002F CAUSED BY: ORG,HIBERNATE.EXCEPTION.SQLGRAMMAREXCEPTION CREATEBREAKPAINT: EPROR PENFORMING ISOLATED  VOKE(EXTENDEDENTIT AT ORG-SPRINGFRANEMONK.ORN- JPA,EXTENDEDENTITYHENAGERCREATORSEXTENDEDEDENTITYHANAGATIONLANDLANDLAR,IN AT JDK.PROXY2\u002FJDK.PROXY2.$PROXY126.PERSIST(UNKNOWN SOURCE) INTERNAL LINES> CE)~[NA:NA] -->\n![](https:\u002F\u002Fcdn.nlark.com\u002Fyuque\u002F0\u002F2026\u002Fpng\u002F751015\u002F1770347434105-042ec749-8b63-4168-bcfe-2a04a1724e83.png)\n\n\n\nhutool-all\n\n```java\n\u003Cdependency>\n    \u003CgroupId>cn.hutool\u003C\u002FgroupId>\n    \u003CartifactId>hutool-all\u003C\u002FartifactId>\n    \u003Cversion>5.8.25\u003C\u002Fversion>\n\u003C\u002Fdependency>\n```\n\n## 配 JAP\n\n```yaml\n  # 配置 jap方言\n  jpa:\n    database-platform: org.hibernate.dialect.MySQLDialect\n    hibernate:\n      ddl-auto: none  # 手动创建数据库\n    show-sql: true\n    properties:\n      hibernate:\n        # 核心配置：格式化 SQL\n        format_sql: true\n        # 高级配置：显示 SQL 里的参数（把 ? 换成实际的值）\n        use_sql_comments: true\n```\n\n## 新增和更新接口\n\n```java\n\u002F**\n * 新增或者更新数据\n *\u002F\n@Operation(summary = \"新增管理员\", description = \"新增管理员对象，提供JSON对象数据\")\n@PostMapping(\"\u002Fsave\")\npublic Result save(@RequestBody Admin admin) {\n    adminService.save(admin);\n    return Result.success();\n}\n```\n\nservice\n\n```java\npublic void save(Admin admin) {\n    if (admin.getId() == null) {  \u002F\u002F 新增  数据库ID是自增\n        \u002F\u002F 判断账户是否重复\n\u002F\u002F            ExampleMatcher matcher = ExampleMatcher.matching().withStringMatcher(ExampleMatcher.StringMatcher.EXACT);\n\u002F\u002F            ExampleMatcher matcher = ExampleMatcher.matching()\n\u002F\u002F                    .withMatcher(\"username\", ExampleMatcher.GenericPropertyMatchers.exact());\n\u002F\u002F            Example\u003CAdmin> example = Example.of(admin, matcher);\n        Admin dbAdmin = adminRepository.findByUsername(admin.getUsername());\n        if (dbAdmin != null) {\n            throw new CustomException(\"账号重复\");\n        }\n        if (admin.getPassword() == null || admin.getPassword().isEmpty()) {\n            admin.setPassword(\"admin\");\n        }\n        if (admin.getName() == null || admin.getName().isEmpty()) {\n            admin.setName(\"管理员\");\n        }\n        admin.setRole(\"管理员\");\n    } else {\n        Admin dbAdmin = adminRepository.findById(admin.getId()).orElse(null);\n        if (dbAdmin != null) {\n            BeanUtil.copyProperties(admin, dbAdmin, CopyOptions.create().setIgnoreNullValue(true));\n            admin = dbAdmin;\n        } else {\n            throw new CustomException(\"数据不存在\");\n        }\n    }\n    adminRepository.save(admin);\n}\n```\n\n## 删除接口\n\n```java\n\u002F**\n * 删除数据\n *\u002F\n@Operation(summary = \"删除管理员\", description = \"删除管理员对象，根据ID删除\")\n@DeleteMapping(\"\u002FdeleteById\u002F{id}\")\npublic Result deleteById(@PathVariable Integer id) {\n    adminService.deleteById(id);\n    return Result.success();\n}\n\n```\n\n## 批量删除接口\n\n```java\n\u002F**\n * 批量删除数据\n *\u002F\n@Operation(summary = \"批量删除管理员\", description = \"批量删除管理员对象，根据ID数组删除\")\n@DeleteMapping(\"\u002FdeleteBatch\")\npublic Result deleteBatch(@RequestBody List\u003CInteger> ids) {\n    adminService.deleteBatch(ids);\n    return Result.success();\n}\n```\n\n## 单个查询\n\n```java\n\u002F**\n * 根据ID查询数据\n *\u002F\n@Operation(summary = \"查询单个管理员\", description = \"返回管理员\")\n@GetMapping(\"\u002FfindById\u002F{id}\")\npublic Result findById(@PathVariable Integer id) {\n    Admin admin = adminService.findById(id);\n    return Result.success(admin);\n}\n```\n\n## 查询所有 \n\n```java\n\u002F**\n * 查询所有的数据\n *\u002F\n@Operation(summary = \"查询所有管理员\", description = \"返回管理员列表\")\n@GetMapping(\"\u002FfindAll\")\npublic Result findAll() {\n    List\u003CAdmin> list = adminService.findAll();\n    return Result.success(list);\n}\n\n```\n\n\n\n## 分页查询接口\n\n```java\n\u002F**\n * 分页查询所有管理员\n *\u002F\n@Operation(summary = \"分页查询所有管理员\", description = \"返回管理员分页列表\")\n@GetMapping(\"\u002FfindPage\")\npublic Result findPage(Admin admin,\n                       @RequestParam(defaultValue = \"1\") Integer pageNum,\n                       @RequestParam(defaultValue = \"10\") Integer pageSize) {\n    PageInfo\u003CAdmin> pageInfo = adminService.findPage(admin, pageNum, pageSize);\n    return Result.success(pageInfo);\n}\n```\n\nservice\n\n```java\npublic PageInfo\u003CAdmin> findPage(Admin admin, Integer pageNum, Integer pageSize) {\n    ExampleMatcher matcher = ExampleMatcher.matching()\n            .withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING)\n            .withIgnoreNullValues();\n    Example\u003CAdmin> example = Example.of(admin, matcher);\n    PageRequest pageRequest = PageRequest.of(pageNum - 1, pageSize).withSort(Sort.by(Sort.Direction.DESC, \"id\"));\n    Page\u003CAdmin> page = adminRepository.findAll(example, pageRequest);\n    return PageInfo.of(page);\n}\n\n```\n\n## 分页对象 PageInfo\n\n```java\n@Data\n@Builder\npublic class PageInfo\u003CT> {\n    private Long total;\n    private List\u003CT> list;\n\n    public static \u003CT> PageInfo\u003CT> of(Page\u003CT> page) {\n        return PageInfo.\u003CT>builder()\n                .total(page.getTotalElements())\n                .list(page.getContent())\n                .build();\n    }\n}\n```\n\n## 自定义异常  CustomException\n\n```java\npackage com.example.exception;\n\npublic class CustomException extends RuntimeException {\n\n    public CustomException(String message) {\n        super(message);\n    }\n\n}\n\n```\n\n## 全局异常处理器\n\n```java\npackage com.example.exception;\n\nimport com.example.common.Result;\nimport lombok.extern.slf4j.Slf4j;\nimport org.springframework.web.bind.annotation.ExceptionHandler;\nimport org.springframework.web.bind.annotation.RestControllerAdvice;\n\n@RestControllerAdvice\n@Slf4j\npublic class GlobalExceptionHandler {\n\n    \u002F**\n     * 处理业务异常（用户主动抛出的信息）\n     *\u002F\n    @ExceptionHandler(CustomException.class)\n    public Result handleCustomException(CustomException e) {\n        log.error(\"业务异常：\", e); \u002F\u002F 打印堆栈日志方便后端排查\n        return Result.error(\"500\", e.getMessage());\n    }\n\n    \u002F**\n     * 处理所有不可知的运行时异常（如数据库报错、空指针）\n     *\u002F\n    @ExceptionHandler(Exception.class)\n    public Result handleException(Exception e) {\n        log.error(\"系统异常：\", e); \u002F\u002F 打印堆栈日志方便后端排查\n        return Result.error(\"500\", \"系统繁忙，请稍后再试\");\n    }\n\n}\n\n```\n\n## ","coding",1,257,2377,"2026-02-06 12:26:55","2026-05-03 22:49:02","2026最新基于SpringBoot4+Vue3零基础入门项目实战教学","springboot4-vue3-tutorial",{"project":18,"items":19},{"id":6,"title":15,"slug":16},[20,28,29,36],{"id":21,"uuid":22,"project_id":6,"title":23,"type":9,"status":10,"public_enabled":10,"views":24,"sort":25,"created_at":26,"updated_at":27,"project_title":15,"project_slug":16},1219,"zz39u4vv","01. SpringBoot4零基础入门实战",745,2376,"2026-02-05 12:35:53","2026-05-07 15:36:12.649662+00",{"id":4,"uuid":5,"project_id":6,"title":7,"type":9,"status":10,"public_enabled":10,"views":11,"sort":12,"created_at":13,"updated_at":14,"project_title":15,"project_slug":16},{"id":30,"uuid":31,"project_id":6,"title":32,"type":9,"status":10,"public_enabled":10,"views":33,"sort":34,"created_at":35,"updated_at":14,"project_title":15,"project_slug":16},1221,"eQlrBI25","03. 使用代码生成器自动生成后端代码",195,2381,"2026-02-09 11:13:19",{"id":37,"uuid":38,"project_id":6,"title":39,"type":9,"status":10,"public_enabled":10,"views":40,"sort":41,"created_at":42,"updated_at":14,"project_title":15,"project_slug":16},1222,"Ni0HTQnR","04. Vue3零基础快速入门实战",228,2387,"2026-02-10 11:39:21"]