SpringBoot集成JPA实现分页和CRUD

SpringBoot集成JPA实现分页和CRUD

文章目录

  • SpringBoot集成JPA实现分页和CRUD
    • pom.xml
    • application.properties
    • addCategory.jsp
    • editCategory.jsp
    • hello.jsp
    • listCategory.jsp
    • Category
    • CategoryDAO
    • CategoryService
    • CategoryServiceImpl
    • Page4Navigator
    • RedisConfig
    • CategoryController
    • HelloController

在这里插入图片描述
在这里插入图片描述
懒得敲代码,直接拷贝: SpringBoot集成JPA实现分页和CRUD

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.2.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.moon</groupId><artifactId>springboot</artifactId><version>0.0.1-SNAPSHOT</version><name>springboot</name><description>springboot</description><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><scope>test</scope></dependency><!--要使用jsp添加这个--><dependency><groupId>org.apache.tomcat.embed</groupId><artifactId>tomcat-embed-jasper</artifactId><scope>provided</scope></dependency><dependency><groupId>javax.servlet</groupId><artifactId>jstl</artifactId><scope>provided</scope></dependency><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><scope>provided</scope></dependency><!--数据库--><!-- mysql--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.30</version></dependency><!-- jpa--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

application.properties

填自己的数据库和密码

spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8
spring.datasource.username=
spring.datasource.password=
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.properties.hibernate.hbm2ddl.auto=update###########################redis#########################
#Redis数据库索引(默认为0)
spring.redis.database=0
#Redis服务器地址
spring.redis.host=127.0.0.1
#Redis服务器连接端口
spring.redis.port=6379
#Redis服务器连接密码(默认为空)
spring.redis.password=
#连接池最大连接数(使用负值表示没有限制)
spring.redis.pool.max-active=10
#连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool.max-wait=-1
#连接池中的最大空闲连接
spring.redis.pool.max-idle=8
#连接池中的最小空闲连接
spring.redis.pool.min-idle=0
#连接超时时间(毫秒)
spring.redis.timeout=0spring.jpa.show-sql=true

addCategory.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<div style="margin: 0px auto; width: 500px"><form action="updateCategory" method="post">name:<input name="name" value="${category.name}"><br><button type="submit">提交</button></form>
</div>

editCategory.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8" isELIgnored="false"%><div style="margin: 0px auto; width: 500px"><form action="updateCategory" method="post">name:<input name="name" value="${c.name}"><br><input name="id" type="hidden" value="${c.id}"><button type="submit">提交</button></form>
</div>

hello.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8" isELIgnored="false"%><div style="margin: 0px auto; width: 500px"><form action="updateCategory" method="post">name:<input name="name" value="${c.name}"><br><input name="id" type="hidden" value="${c.id}"><button type="submit">提交</button></form>
</div>

listCategory.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%><%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<div align="center"></div>
<div style="width: 500px;margin: 20px auto;text-align: center"><table align="center" border="1" cellspacing="0"><caption>员工<a href="addCategory">添加</a></caption><thead><tr><th>id</th><th>name</th><th>编辑</th><th>删除</th></tr></thead><tbody><c:forEach items="${page.content}" var="c" varStatus="st"><tr><td>${c.id}</td><td>${c.name}</td><td><a href="editCategory?id=${c.id}">编辑</a></td><td><a href="deleteCategory?id=${c.id}">删除</a></td></tr></c:forEach></tbody></table><div><a href="?start=0">【首页】</a><a href="?start=${page.number-1}">【上一页】</a><a href="?start=${page.number+1}">【下一页】</a><a href="?start=${page.totalPages-1}">【末页】</a></div><div></div>
</div>

Category

package com.moon.springboot.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import javax.persistence.*;/*** @Author moon* @Date 2023/9/26 21:05* @Description*/
@Entity
@Table(name = "category_")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Category {@Id//表明自增长方式@GeneratedValue(strategy = GenerationType.IDENTITY)@Column(name = "id")private Integer id;@Column(name = "name")private String name;
}

CategoryDAO

package com.moon.springboot.dao;import com.moon.springboot.pojo.Category;
import org.springframework.data.jpa.repository.JpaRepository;/*** @Author moon* @Date 2023/9/26 21:18* @Description* 泛型<Category, Integer> 表示这个是针对Category类的DAO,Integer表示主键是Integer类型。* JpaRepository 这个父接口,就提供了CRUD, 分页等等一系列的查询了*/
public interface CategoryDAO extends JpaRepository<Category, Integer> {
}

CategoryService

package com.moon.springboot.service;import com.moon.springboot.pojo.Category;
import com.moon.springboot.util.Page4Navigator;
import org.springframework.data.domain.Pageable;public interface CategoryService {public Page4Navigator<Category> list(Pageable pageable);public void save(Category category);public void delete(int id);public Category get(int id);
}

CategoryServiceImpl

package com.moon.springboot.service.impl;import com.moon.springboot.dao.CategoryDAO;
import com.moon.springboot.pojo.Category;
import com.moon.springboot.service.CategoryService;
import com.moon.springboot.util.Page4Navigator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;@Service
@CacheConfig(cacheNames="category")
public class CategoryServiceImpl implements CategoryService {@AutowiredCategoryDAO categoryDAO;@Override@Cacheable(key="'category '+#p0.offset + '-' + #p0.pageSize ")public Page4Navigator<Category> list(Pageable pageable) {Page<Category> pageFromJPA=  categoryDAO.findAll(pageable);Page4Navigator<Category> page = new Page4Navigator<>(pageFromJPA,5);return page;}@Override@Cacheable(key="'category '+ #p0")public Category get(int id) {Category c =categoryDAO.getOne(id);return c;}@Override@CacheEvict(allEntries=true)
//  @CachePut(key="'category '+ #p0")public void save(Category category) {// TODO Auto-generated method stubcategoryDAO.save(category);}@Override@CacheEvict(allEntries=true)
//  @CacheEvict(key="'category '+ #p0")public void delete(int id) {// TODO Auto-generated method stubcategoryDAO.deleteById(id);}}

Page4Navigator

package com.moon.springboot.util;import java.util.List;import org.springframework.data.domain.Page;public class Page4Navigator<T> {Page<T> page4jpa;//导航分页的页码数int navigatePages;//要打印的总页数int totalPages;int number;long totalElements;int size;int numberOfElements;List<T> content;boolean isHasContent;boolean first;boolean last;boolean isHasNext;boolean isHasPrevious;int[] navigatepageNums;public Page4Navigator() {//这个空的分页是为了 Redis 从 json格式转换为 Page4Navigator 对象而专门提供的}public Page4Navigator(Page<T> page4jpa,int navigatePages) {this.page4jpa = page4jpa;this.navigatePages = navigatePages;totalPages = page4jpa.getTotalPages();number  = page4jpa.getNumber() ;totalElements = page4jpa.getTotalElements();size = page4jpa.getSize();numberOfElements = page4jpa.getNumberOfElements();content = page4jpa.getContent();isHasContent = page4jpa.hasContent();first = page4jpa.isFirst();last = page4jpa.isLast();isHasNext = page4jpa.hasNext();isHasPrevious  = page4jpa.hasPrevious();calcNavigatepageNums();}private void calcNavigatepageNums() {int navigatepageNums[];int totalPages = getTotalPages();int num = getNumber();//当总页数小于或等于导航页码数时if (totalPages <= navigatePages) {navigatepageNums = new int[totalPages];for (int i = 0; i < totalPages; i++) {navigatepageNums[i] = i + 1;}} else { //当总页数大于导航页码数时navigatepageNums = new int[navigatePages];int startNum = num - navigatePages / 2;int endNum = num + navigatePages / 2;if (startNum < 1) {startNum = 1;//(最前navigatePages页for (int i = 0; i < navigatePages; i++) {navigatepageNums[i] = startNum++;}} else if (endNum > totalPages) {endNum = totalPages;//最后navigatePages页for (int i = navigatePages - 1; i >= 0; i--) {navigatepageNums[i] = endNum--;}} else {//所有中间页for (int i = 0; i < navigatePages; i++) {navigatepageNums[i] = startNum++;}}}this.navigatepageNums = navigatepageNums;}public int getNavigatePages() {return navigatePages;}public void setNavigatePages(int navigatePages) {this.navigatePages = navigatePages;}public int getTotalPages() {return totalPages;}public void setTotalPages(int totalPages) {this.totalPages = totalPages;}public int getNumber() {return number;}public void setNumber(int number) {this.number = number;}public long getTotalElements() {return totalElements;}public void setTotalElements(long totalElements) {this.totalElements = totalElements;}public int getSize() {return size;}public void setSize(int size) {this.size = size;}public int getNumberOfElements() {return numberOfElements;}public void setNumberOfElements(int numberOfElements) {this.numberOfElements = numberOfElements;}public List<T> getContent() {return content;}public void setContent(List<T> content) {this.content = content;}public boolean isHasContent() {return isHasContent;}public void setHasContent(boolean isHasContent) {this.isHasContent = isHasContent;}public boolean isFirst() {return first;}public void setFirst(boolean first) {this.first = first;}public boolean isLast() {return last;}public void setLast(boolean last) {this.last = last;}public boolean isHasNext() {return isHasNext;}public void setHasNext(boolean isHasNext) {this.isHasNext = isHasNext;}public boolean isHasPrevious() {return isHasPrevious;}public void setHasPrevious(boolean isHasPrevious) {this.isHasPrevious = isHasPrevious;}public int[] getNavigatepageNums() {return navigatepageNums;}public void setNavigatepageNums(int[] navigatepageNums) {this.navigatepageNums = navigatepageNums;}}

RedisConfig

package com.moon.springboot.config;import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.*;import java.time.Duration;@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {private RedisSerializer<String> keySerializer() {return new StringRedisSerializer();}private RedisSerializer<Object> valueSerializer() {return new GenericJackson2JsonRedisSerializer();//value值使用json序列化器}@Beanpublic CacheManager cacheManager(RedisConnectionFactory factory) {RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();redisCacheConfiguration = redisCacheConfiguration.entryTtl(Duration.ofMinutes(30L))//设置缓存延时时间为30分钟.disableCachingNullValues()//如果是空值,不缓存.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(keySerializer()))//设置key值序列化.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(valueSerializer()));//设置value值序列化为jsonreturn RedisCacheManager.builder(RedisCacheWriter.nonLockingRedisCacheWriter(factory)).cacheDefaults(redisCacheConfiguration).build();}
}

CategoryController

package com.moon.springboot.web;import com.moon.springboot.pojo.Category;
import com.moon.springboot.service.CategoryService;
import com.moon.springboot.util.Page4Navigator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;@Controller
public class CategoryController {@AutowiredCategoryService categoryService;@RequestMapping("/listCategory")public String listCategory(Model m,@RequestParam(value = "start", defaultValue = "0") int start,@RequestParam(value = "size", defaultValue = "5") int size) throws Exception {start = start<0?0:start;Sort sort = Sort.by(Sort.Direction.DESC, "id");Pageable pageable = PageRequest.of(start, size, sort);Page4Navigator<Category> page =categoryService.list(pageable);m.addAttribute("page", page);return "listCategory";}@RequestMapping("/addCategory")public String addCategory(Category c) throws Exception {categoryService.save(c);return "redirect:listCategory";}@RequestMapping("/deleteCategory")public String deleteCategory(Category c) throws Exception {categoryService.delete(c.getId());return "redirect:listCategory";}@RequestMapping("/updateCategory")public String updateCategory(Category c) throws Exception {categoryService.save(c);return "redirect:listCategory";}@RequestMapping("/editCategory")public String editCategory(int id,Model m) throws Exception {Category c= categoryService.get(id);m.addAttribute("c", c);return "editCategory";}
}

HelloController

package com.moon.springboot.web;import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.text.DateFormat;
import java.util.Date;/*** @Author moon* @Date 2023/9/25 21:17* @Description*/@Controller
public class HelloController {@RequestMapping("/hello")public String hello(Model model) {model.addAttribute("now", DateFormat.getDateTimeInstance().format(new Date()));return "hello";}@RequestMapping("/hello_1")public String hello_1(Model model) {model.addAttribute("now", DateFormat.getDateTimeInstance().format(new Date()));return "hello_1";}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/129872.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于Springboot+MYSQL+Maven实现的宠物医院管理系统(源码+数据库+运行指导文档+项目运行指导视频)

一、项目简介 本项目是一套基于springboot框架实现的宠物医院管理系统 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff0c;eclipse或者idea 确保可以运行&#xff01; 该系统功能完善、界面美观、操作简单…

【Kubernetes】初识k8s--扫盲阶段

文章目录 1、k8s概述2、为什么要有k8s2.1 回顾以往的应用部署方式2.2 容器具有的优势 3、k8s能带来什么 1、k8s概述 kubernetes是一个可移植、可扩展的开源平台&#xff0c;用于管理 容器化 的工作负载和服务&#xff0c;可促进申明式配置和自动化。kubernetes拥有一个庞大且快…

ElasticSearch深度解析入门篇:高效搜索解决方案的介绍与实战案例讲解,带你避坑

ElasticSearch深度解析入门篇&#xff1a;高效搜索解决方案的介绍与实战案例讲解&#xff0c;带你避坑 1.Elasticsearch 产生背景 大规模数据如何检索 如&#xff1a;当系统数据量上了 10 亿、100 亿条的时候&#xff0c;我们在做系统架构的时候通常会从以下角度去考虑问题&a…

【C语法学习】15 - fopen()函数

文章目录 1 函数原型2 返回值3 参数3.1 文件名3.2 模式3.2.1 以"r"模式打开3.2.2 以"w"模式打开3.2.3 以"a"模式打开3.2.4 以"r"模式打开3.2.5 以"w"模式打开3.2.6 以"a"模式打开 1 函数原型 fopen()&#xff1a…

右击显示Pycharm打开教程

效果图 操作流程 win r 输入 regedit 回车打开注册表编辑器 2.找到 shell 路径 计算机\HKEY_CLASSES_ROOT\Directory\shell3.在 shell 下新建项&#xff0c;名称为 Pycharm 单击Pycharm文件夹&#xff0c;双击默认项&#xff0c;修改默认值&#xff0c;这个数值就是你右击后…

【Linux】 shutdown 命令使用

shutdown 命令可以用来进行关机程序&#xff0c;并且在关机以前传送讯息给所有使用者正在执行的程序&#xff0c;shutdown 也可以用来重开机。使用权限&#xff1a;系统管理者。 语法 shutdown [选项] 时间 [警告信息] 命令选项及作用 执行令 man shutdown 执行命令结果 参…

计算虚拟化2——内存虚拟化

目录 物理机内存访问过程 虚拟地址VA和物理地址PA概念 MUU实现VA到PA所使用的映射表 内存虚拟化类型 内存软件辅助虚拟化 内存硬件辅助虚拟化 内存虚拟化-内存超分配 内存共享 内存置换 内存气泡 物理机内存访问过程 内存的基本知识 内存都是从物理地址0开始的&…

golang工程——opentelemetry简介、架构、概念、追踪原理

opentelemetry 简介 OpenTelemetry&#xff0c;简称OTel&#xff0c;是一个与供应商无关的开源可观测性框架&#xff0c;用于检测、生成、收集和导出 遥测数据&#xff0c;如轨迹、度量、日志。OTel的目标是提供一套标准化的供应商无关SDK、API和工具&#xff0c;用于接 收、…

阿里云免费服务器

文章目录 最近的阿里云活动By the way在云服务器ECS上搭建个人网站正文补充:定期释放补充:不知道阿里云服务器的密码怎么办?成果补充&#xff1a;怎么找到实例操作的后台&#xff1f;补充&#xff1a;怎么查看服务器到期时间&#xff1f; 究竟白嫖了多少&#xff1f;最后&…

[论文笔记]RetroMAE

引言 RetroMAE,中文题目为 通过掩码自编码器预训练面向检索的语言模型。 尽管现在已经在许多重要的自然语言处理任务上进行了预训练,但对于密集检索来说,仍然需要探索有效的预训练策略。 本篇工作,作者提出RetroMAE,一个新的基于掩码自编码器(Masked Auto-Encoder,MAE)…

【leetcode】17.04 消失的数字

目录 1. 思路2. 代码 题目链接&#xff1a;leetcode 17.04.消失的数字 题目描述&#xff1a; 1. 思路 要求算法复杂度为O(n)&#xff0c;有两种方式&#xff1a; &#xff08;1&#xff09;利用异或交换律 与nums所有元素异或一遍&#xff1b;与0-n的值异或&#xff0c;n…

开源 | 30余套STM32单片机、嵌入式Linux、物联网、人工智能项目(开发板+教程+视频)

文末免费领取&#xff01; 30余套综合项目案例 STM32单片机、嵌入式、物联网、人工智能 项目文档源码视频 高校教学、学生毕设、个人项目练手 嵌入式实战项目推荐 15个嵌入式LinuxQt综合应用项目&#xff0c;涉及家居、医疗、农业等多种应用领域&#xff0c;案例中使用了嵌…

Linux高级命令(扩展)二

一、Linux下用户管理 1、用户概念以及基本作用 用户&#xff1a;指的是Linux操作系统中用于管理系统或者服务的人 一问&#xff1a;管理系统到底在管理什么&#xff1f; 答&#xff1a;Linux下一切皆文件&#xff0c;所以用户管理的是相应的文件 二问&#xff1a;如何管理…

【自用】vmware workstation建立主机window与虚拟机ubuntu之间的共享文件夹

1.在windows中建立1个文件夹 在vmware中设置为共享文件夹 参考博文&#xff1a; https://zhuanlan.zhihu.com/p/650638983 2.解决&#xff1a; &#xff08;1&#xff09;fuse: mountpoint is not empty &#xff08;2&#xff09;普通用户也能使用共享目录 参考博文&#x…

大模型 其他方案的进度

Llama2 1、中文提问&#xff0c;英文的回答&#xff0c;对于中文不友好 2、网上还没有看到很详细的微调教程 3、虽然Llama2的预训练数据相对于第一代LLaMA扩大了一倍&#xff0c;但是中文预训练数据的比例依然非常少&#xff0c;仅占0.13%&#xff0c;这也导致了原始Llama2的中…

多模态大模型最全综述

由微软7位华人研究员撰写--多模态基础模型已经从专用走向通用 它从目前已经完善的和还处于最前沿的两类多模态大模型研究方向出发&#xff0c;全面总结了五个具体研究主题&#xff1a; 视觉理解视觉生成统一视觉模型LLM加持的多模态大模型多模态agent 1、谁适合阅读这份综述&…

Vue3问题:如何实现组件拖拽实时预览功能?

前端功能问题系列文章&#xff0c;点击上方合集↑ 序言 大家好&#xff0c;我是大澈&#xff01; 本文约3000字&#xff0c;整篇阅读大约需要5分钟。 本文主要内容分三部分&#xff0c;第一部分是需求分析&#xff0c;第二部分是实现步骤&#xff0c;第三部分是问题详解。 …

运维基础-Docker容器命令部署

Docker基础知识 安装问题-有podmanCentos8使用yum install docker -y时&#xff0c;默认安装的是podman-docker软件安装docker yum list installed | grep dockeryum -y remove xxxxDocker安装配置下载安装docker启动docker&#xff0c;并设置开机启动下载所需镜像 centos镜像进…

【报错】错误 C1004 :发现意外的文件尾

文章目录 情景在现出错原因解决方案问题解决 情景在现 出错原因 这个错误通常是由于您在源文件中漏写了某些括号或者分号&#xff0c;导致编译器在处理到文件末尾时发现没有遇到预期的符号。 解决方案 解决这个错误的方法是&#xff0c;打开您的源文件&#xff0c;仔细检查是否…

EMC Unity存储系统如何查看SSD的使用寿命

为什么要写这个博客&#xff1f; 客户对老的EMC unity的存储系统要扩容&#xff0c;如何确定SSD磁盘是全新的还是拆机二手的&#xff1f;很多时候客户还有一个奇葩的要求&#xff0c;就是要和5年前的磁盘PN一致&#xff0c;甚至要求固件版本一致&#xff0c;最关键的还要求是全…