idea+vue3+mybatis+springBoot3前后端分离实现对一张表的增删改查(完整代码版)

这篇文章的避雷点:不涉及知识讲解只有操作,所以没有java基础和,javaweb基础和前端基础的兄弟请谨慎考虑以这篇文章来学习前后端分离,当然兄弟可以结合ai来学习这篇文章的知识点。

这篇文章所使用的软件及环境条件:mysql 8.0.32 , node.js v20.17.0,navicat 16.1.9,

idea 2024.3.2旗舰版 , Vue @vue/cli 5.0.8,postman

这文章灵感:是结合程序员青哥的教学项目,bilibili视频 《【 免费学习】1天学会SpringBoot3+Vue3实战项目开发,手把手带你做完整的前后端分离项目,适合计算机毕业设计、实习项目、Java、Vue编程练手项目**》** 和 我自身的知识储备所编写的学习笔记

后端项目位置: Admin/zwy_manager_back_v1

前端项目地址:Admin/zwy_manager_up_v1

1.后端项目

1.1数据库搭建

新建一个数据库

将下面sql执行

sql 复制代码
/*
 Navicat Premium Data Transfer

 Source Server         : javaEE
 Source Server Type    : MySQL
 Source Server Version : 80032 (8.0.32)
 Source Host           : localhost:3306
 Source Schema         : zwy

 Target Server Type    : MySQL
 Target Server Version : 80032 (8.0.32)
 File Encoding         : 65001

 Date: 05/04/2025 11:05:52
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for employee
-- ----------------------------
DROP TABLE IF EXISTS `employee`;
CREATE TABLE `employee`  (
  `id` int UNSIGNED NOT NULL AUTO_INCREMENT,
  `name` char(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
  `gender` enum('男','女') CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '男',
  `title` char(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
  `birthday` date NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1005 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of employee
-- ----------------------------
INSERT INTO `employee` VALUES (1001, '张三', '男', '高级工程师', '1985-01-01');
INSERT INTO `employee` VALUES (1002, '李四', '女', '助工', '1995-01-01');
INSERT INTO `employee` VALUES (1003, '王五', '男', '工程师', '1988-11-11');
INSERT INTO `employee` VALUES (1004, '赵六', '男', '工程师', '1988-12-12');

SET FOREIGN_KEY_CHECKS = 1;

1.2后端项目搭建

1.2.1使用idea内置的spring initializr创建项目

1.2.2项目的基本结构

1.2.2.1数据库连接测试

在application.properties中配置数据库(注意修改你的数据库名称和你mysql的用户和密码)

sql 复制代码
spring.application.name=zwy_manager_back_v1
# 数据库配置
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/zwy?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
spring.datasource.username=root
spring.datasource.password=123456

在ZwyManagerBackV1ApplicationTests.java 编写数据库连接测试方法

java 复制代码
@SpringBootTest
class ZwyManagerBackV1ApplicationTests {
    @Resource
    private DataSource dataSource;

    @Test
    void contextLoads() {
    }
    @Test
    void testDataSource() throws Exception {
        System.out.println(dataSource.getClass().getName());
        System.out.println(dataSource.getConnection());
    }


}

正确测试结果(如果没有成功请仔细检查application.properties中配置数据库)

1.2.2.2创建实体类

位置:src/main/java/com/cdp/zwy/zwy_manager_back_v1/entity

名称:Employee

sql 复制代码
@Data
public class Employee {
    private Integer id;
    private String name;
    private String gender;
    private String title;
    private Date birthday;
}

1.3使用mybatis对employee表进行增删改查

1.3.1配置端口号和mybatis实体和xml的映射

在application.properties中添加

sql 复制代码
# 端口号
server.port=9999
#配置mybatis实体和xml映射
mybatis.mapper-locations=classpath:mapper/*Mapper.xml

1.3.2编写mapper接口和它的xml映射文件(持久层)

1.3.2.1编写mapper接口

位置:src/main/java/com/cdp/zwy/zwy_manager_back_v1/mapper

名称:EmployeeMapper

sql 复制代码
@Mapper
public interface EmployeeMapper {
    int insert(Employee employee);
    int deleteById(Integer id);
    int update(Employee employee);
    Employee selectById(Integer id);
    List<Employee> selectAll();
}
1.3.2.2编写xml映射文件

位置:src/main/resources/mapper

名称:EmployeeMapper.xml

XML 复制代码
<?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.cdp.zwy.zwy_manager_back_v1.mapper.EmployeeMapper">
    <resultMap id="employeeResultMap" type="com.cdp.zwy.zwy_manager_back_v1.entity.Employee">
    </resultMap>
    <insert id="insert" parameterType="com.cdp.zwy.zwy_manager_back_v1.entity.Employee">
        insert into employee(name,gender,title,birthday) values(#{name},#{gender},#{title},#{birthday})
    </insert>
    <delete id="deleteById" parameterType="int">
        delete from employee where id=#{id}
    </delete>
    <update id="update" parameterType="com.cdp.zwy.zwy_manager_back_v1.entity.Employee">
        update employee set name=#{name},gender=#{gender},title=#{title},birthday=#{birthday} where id=#{id}
    </update>
    <select id="selectById" parameterType="int" resultMap="employeeResultMap">
        select * from employee where id=#{id}
    </select>
    <select id="selectAll" resultMap="employeeResultMap">
        select * from employee
    </select>

    
</mapper>

1.3.3编写sevice层调用mapper接口(业务层)

位置:src/main/java/com/cdp/zwy/zwy_manager_back_v1/service

名称:EmployeeService

java 复制代码
@Service
public class EmployeeService {
    @Resource
    private EmployeeMapper employeeMapper;
    public int add(Employee employee) {
        int row =  employeeMapper.insert(employee);
        if(row!=1){
            throw new RuntimeException("添加失败");
        }
        return row;
    }
    public int deleteById(Integer id) {
        int row =  employeeMapper.deleteById(id);
        if(row!=1){
            throw new RuntimeException("删除失败");
        }
        return row;
    }
    public int modify(Employee employee) {
        int row =  employeeMapper.update(employee);
        if(row!=1){
            throw new RuntimeException("更新失败");
        }
        return row;
    }
    public Employee findById(Integer id) {
        return employeeMapper.selectById(id);
    }
    public List<Employee> findAll() {
        return employeeMapper.selectAll();
    }
}

1.3.4编写controller层(控制层 api)

控制层调用业余层

位置:src/main/java/com/cdp/zwy/zwy_manager_back_v1/controller

名称:EmployeeController

java 复制代码
@RestController
@RequestMapping("/employee")
public class EmployeeController {
    @Resource
    private EmployeeService employeeService;
    @PostMapping("/add")
    public int add(@RequestBody Employee employee){
        return employeeService.add(employee);
    }
    @GetMapping("/findAll")
    public List<Employee> findAll(){
        return employeeService.findAll();
    }
    @GetMapping("/findById/{id}")
    public Employee findById(@PathVariable Integer id){
        return employeeService.findById(id);
    }
    @DeleteMapping("/deleteById/{id}")
    public int deleteById(@PathVariable Integer id){
        return employeeService.deleteById(id);
    }
    @PutMapping("/modify")
    public int modify(@RequestBody Employee employee){
        return employeeService.modify(employee);
    }

}

1.3.4测试接口层(控制层)

1.3.4.1浏览器测试Get请求方式的API

employee表数据

复制代码
http://localhost:9999/employee/findAll
复制代码
http://localhost:9999/employee/findById/1001
1.3.4.2postman测试delete,put,post请求方式的API(或者在API测试工具)
java 复制代码
localhost:9999/employee/deleteById/1004
java 复制代码
localhost:9999/employee/add
XML 复制代码
localhost:9999/employee/modify

到这里,你已经掌握了 MyBatis 对一张表的增删改查操作,但这还不够。虽然上面的代码实现了基本功能,但仍存在一些不足至少有以下两点:

第一点:接口返回值不够规范:

例如,find 方法返回实体对象或对象列表,增删改操作返回影响行数。这种返回值方式在前后端分离的项目中不够统一,我们需要定义一个通用的返回对象,便于前端处理。

第二点:异常处理不够完善:

当前代码缺乏自定义异常处理机制,这会导致问题定位困难。我们需要引入自定义异常,以便快速定位和处理问题。

通过优化这两点,我们可以让代码更加规范、健壮,并更好地支持前后端分离的开发模式。

1.4接口层的返回统一对象并且实施异常处理

1.4.1编写Result统一返回类

位置:src/main/java/com/cdp/zwy/zwy_manager_back_v1/common

名称:Result

java 复制代码
@Data
public class Result {
    private String code;
    private String msg;
    private Object data;

    public Result() {
    }

    public Result(String code, String msg, Object data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }
    public static Result success() {
        return new Result("200", "success", null);
    }
    public static Result success(Object data) {
        return new Result("200", "success", data);
    }
    public static Result error() {
        return new Result("500", "请求失败", null);
    }
    public static Result error(String code,String msg) {
        return new Result(code, msg, null);
    }

}

1.4.2编写错误码枚举类

位置:src/main/java/com/cdp/zwy/zwy_manager_back_v1/common

名称:ErrorCode

java 复制代码
public enum ErrorCode {
        NOT_DATA("10000","没有数据"),
        EMPLOYEE_NOT_FOUND("10001", "该员工不存在"),
        EMPLOYEE_ADD_ERROR("10002", "添加员工失败"),
        EMPLOYEE_DELETE_ERROR("10003", "删除员工失败"),
        EMPLOYEE_MODIFY_ERROR("10004", "修改员工失败");


        private final String code;
        private final String msg;

        ErrorCode(String code, String msg) {
            this.code = code;
            this.msg = msg;
        }

        public String getCode() {
            return code;
        }

        public String getMsg() {
            return msg;
        }
    }

1.4.3编写业务层的异常处理类

位置:src/main/java/com/cdp/zwy/zwy_manager_back_v1/common

名称:EmployeeServiceException

java 复制代码
public class EmployeeServiceException extends RuntimeException {
    private final ErrorCode errorCode;
    public EmployeeServiceException(ErrorCode errorCode) {
        super(errorCode.getMsg());
        this.errorCode = errorCode;
    }
    public ErrorCode getErrorCode() {
        return errorCode;
    }
}

1.4.4修改业务层使用异常处理

位置:src/main/java/com/cdp/zwy/zwy_manager_back_v1/service

名称:EmployeeService

java 复制代码
@Service
public class EmployeeService {
    @Resource
    private EmployeeMapper employeeMapper;
    public int add(Employee employee) {
        int row =  employeeMapper.insert(employee);
        if(row!=1){
            throw new EmployeeServiceException(ErrorCode.EMPLOYEE_ADD_ERROR);
        }
        return row;
    }
    public int deleteById(Integer id) {
         Employee employee = employeeMapper.selectById(id);
         if (employee == null){
             throw new EmployeeServiceException(ErrorCode.EMPLOYEE_NOT_FOUND);
         }
        int row =  employeeMapper.deleteById(id);
        if(row!=1){
            throw new EmployeeServiceException(ErrorCode.EMPLOYEE_DELETE_ERROR);
        }
        return row;
    }
    public int modify(Employee employee) {
        Employee employee1 = employeeMapper.selectById(employee.getId());
        if (employee1 == null){
            throw new EmployeeServiceException(ErrorCode.EMPLOYEE_NOT_FOUND);
        }
        int row =  employeeMapper.update(employee);
        if(row!=1){
            throw new EmployeeServiceException(ErrorCode.EMPLOYEE_MODIFY_ERROR);
        }
        return row;
    }
    public Employee findById(Integer id) {
        Employee employee = employeeMapper.selectById(id);
        if(employee == null){
            throw new EmployeeServiceException(ErrorCode.EMPLOYEE_NOT_FOUND);
        }
        return employee;
    }
    public List<Employee> findAll() {
        List<Employee> employees = employeeMapper.selectAll();
        if(employees.size() == 0){
            throw new EmployeeServiceException(ErrorCode.NOT_DATA);
        }
        return employees;
    }
}

1.4.5修改控制层(接口层)的方法返回值

位置:src/main/java/com/cdp/zwy/zwy_manager_back_v1/controller

名称:EmployeeController

java 复制代码
@RestController
@RequestMapping("/employee")
public class EmployeeController {
    @Resource
    private EmployeeService employeeService;
    @PostMapping("/add")
    public Result add(@RequestBody Employee employee){
        return Result.success(employeeService.add(employee));
    }
    @GetMapping("/findAll")
    public Result findAll(){
        return Result.success(employeeService.findAll());
    }
    @GetMapping("/findById/{id}")
    public Result findById(@PathVariable Integer id){
        return Result.success(employeeService.findById(id)); 
    }
    @DeleteMapping("/deleteById/{id}")
    public Result deleteById(@PathVariable Integer id){
        return Result.success(employeeService.deleteById(id));
    }
    @PutMapping("/modify")
    public Result modify(@RequestBody Employee employee){
        return Result.success(employeeService.modify(employee));
    }

}

1.4.6编写全局异常处理类

位置:src/main/java/com/cdp/zwy/zwy_manager_back_v1/exception

名称:GlobalExceptionHandler

java 复制代码
@ControllerAdvice
public class GlobalExceptionHandler {
    private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    @ExceptionHandler(EmployeeServiceException.class)
    public ResponseEntity<Result> handleEmployeeServiceException(EmployeeServiceException ex) {
        // 记录日志
        log.error("业务异常: 错误码={}, 错误信息={}", ex.getErrorCode().getCode(), ex.getErrorCode().getMsg(), ex);

        // 返回统一错误响应
        Result response = new Result(
                ex.getErrorCode().getCode(),
                ex.getErrorCode().getMsg(),
                null
        );
        return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST);
    }
}

还需要导入两个maven依赖坐标,在pom.xml<dependencies></dependencies>标签里加

XML 复制代码
    <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>2.1.0-alpha1</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.5.18</version>
            <scope>compile</scope>
        </dependency>

1.4.7测试修改后是够可以正常使用

许多bug是在更改中产生的,当然存在bug我肯定会改上面的代码,所以你是看不到bug的哈哈哈

依旧测试api,我这里测试和1.3.4是一样的操作我在重复一编保证逻辑的完整性,你如果很强可以不看这个自己尝试。

1.4.7.1浏览器测试Get请求方式的API

employee表数据

复制代码
http://localhost:9999/employee/findAll
复制代码
http://localhost:9999/employee/findById/1001

这里我只展示一个业务层的异常抛出哈,其他的异常触发你们自己去告一哈。

查询一个没有的员工

java 复制代码
http://localhost:9999/employee/findById/100
1.4.7.2postman测试delete,put,post请求方式的API(或者在API测试工具)
java 复制代码
localhost:9999/employee/deleteById/1005
java 复制代码
localhost:9999/employee/add
XML 复制代码
localhost:9999/employee/modify

1.5加入分页查询

1.5.1maven引入pageHelper

位置:pom.xml <dependencies></dependencies>标签里

XML 复制代码
    <!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper-spring-boot-starter -->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>2.1.0</version>
        </dependency>

1.5.2在业务层中添加分页查询方法

位置:src/main/java/com/cdp/zwy/zwy_manager_back_v1/service/EmployeeService.java

java 复制代码
   /**
     * 分页查询
     * @param pageNum
     * @param pageSize
     * @return
     */
    public PageInfo<Employee> selectPage(Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum,pageSize);
        List<Employee> list = employeeMapper.selectAll();

        return PageInfo.of(list);
    }

1.5.3在控制层调用该方法

位置:src/main/java/com/cdp/zwy/zwy_manager_back_v1/controller/EmployeeController.java

java 复制代码
    @GetMapping("/selectPage")
    public Result selectPage(@RequestParam(defaultValue = "1") Integer pageNum, @RequestParam(defaultValue = "2") Integer pageSize){
        return Result.success(employeeService.selectPage(pageNum,pageSize));
    }

1.5.4启动项目测试该接口

java 复制代码
http://localhost:9999/employee/selectPage

1.5.5前端涉及到一个根据员工名称模糊分页查询,考虑到拓展直接传入Employee类型对象

所以要添加一个api接口

接口层:

位置:src/main/java/com/cdp/zwy/zwy_manager_back_v1/controller/EmployeeController.java

java 复制代码
  @PostMapping("/findByName")
    public Result findByName(@RequestBody Employee employee, @RequestParam(defaultValue = "1") Integer pageNum, @RequestParam(defaultValue = "2") Integer pageSize){
        return Result.success(employeeService.findByName(pageNum, pageSize,employee.getName()));
    }

业务层:

位置:src/main/java/com/cdp/zwy/zwy_manager_back_v1/service/EmployeeService.java

java 复制代码
    public PageInfo<Employee> findByName(Integer pageNum, Integer pageSize, String name) {
        PageHelper.startPage(pageNum,pageSize);
        List<Employee> list = employeeMapper.selectFuzzy(name);

        return PageInfo.of(list);
    }

持久层:

位置:src/main/java/com/cdp/zwy/zwy_manager_back_v1/mapper/EmployeeMapper.java

java 复制代码
    List<Employee> selectFuzzy(String name);

位置:src/main/resources/mapper/EmployeeMapper.xml

XML 复制代码
    <select id="selectFuzzy" resultMap="employeeResultMap">
        select * from employee where 1 = 1
                                    and
                                   <if test="#{name}!=null">
                                   name like concat('%',#{name},'%')
                                  </if>


    </select>

测试该接口

1.6跨域请求

我们知道后端项目和前端项目是分离的,后端项目启动占用一个端口,前端项目启动占用一个端口

这是前端的一个按钮可能会调用有后端的一个api结构,这是就是跨域请求。这个项目是用的axios发送的请求,跨域配置在后端配置

位置:src/main/java/com/cdp/zwy/background_manager_back/config/CorsConfig.java

java 复制代码
@Configuration
public class CorsFilter {
    @Bean
    public CorsFilter corsFiler(){
        UrlBasedCorsConfigurationSource source  = new UrlBasedCorsConfigurationSource();
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        //1.设置访问源地址(任意地址可以访问,这里可以想象如果两台pc端链接是否可以直接在pc1部署后端,pc2部署前端)
        corsConfiguration.addAllowedOrigin("*");
        //2.设置访问源请求头
        corsConfiguration.addAllowedHeader("*");
        //3.设置访问源请求方法
        corsConfiguration.addAllowedMethod("*");
        //4.对接口配置跨域设置
        source.registerCorsConfiguration("/**",corsConfiguration);

        return new CorsFilter();
    }

1.7往数据库添加点数据

注意id不能重复,你可也先将数据全删掉再添加数据

sql 复制代码
use zwy
INSERT INTO `employee` VALUES (1001, '赵敏', '女', '资深数据分析师', '1985-03-15');
INSERT INTO `employee` VALUES (1002, '孙涛', '男', '初级程序员', '1998-06-20');
INSERT INTO `employee` VALUES (1003, '周杰', '男', '高级产品经理', '1982-09-30');
INSERT INTO `employee` VALUES (1004, '吴静', '女', '资深UI设计师', '1987-04-22');
INSERT INTO `employee` VALUES (1005, '郑强', '男', '初级运维工程师', '1999-01-10');
INSERT INTO `employee` VALUES (1006, '王丽', '女', '高级市场专员', '1989-07-18');
INSERT INTO `employee` VALUES (1007, '刘洋', '男', '资深架构师', '1978-11-25');
INSERT INTO `employee` VALUES (1008, '陈静', '女', '初级文案策划', '1996-03-05');
INSERT INTO `employee` VALUES (1009, '杨光', '男', '高级销售经理', '1984-05-12');
INSERT INTO `employee` VALUES (1010, '李娜', '女', '资深人力资源专员', '1986-08-08');
INSERT INTO `employee` VALUES (1011, '张伟', '男', '初级财务助理', '1997-02-28');
INSERT INTO `employee` VALUES (1012, '赵丽', '女', '高级技术专家', '1983-10-01');
INSERT INTO `employee` VALUES (1013, '孙强', '男', '资深测试工程师', '1980-07-20');
INSERT INTO `employee` VALUES (1014, '周梅', '女', '初级运营专员', '1995-04-15');
INSERT INTO `employee` VALUES (1015, '吴涛', '男', '高级项目经理', '1981-09-10');
INSERT INTO `employee` VALUES (1016, '郑丽', '女', '资深法律顾问', '1985-03-05');
INSERT INTO `employee` VALUES (1017, '王强', '男', '初级技术支持', '1998-06-30');
INSERT INTO `employee` VALUES (1018, '刘静', '女', '高级市场分析师', '1987-08-12');
INSERT INTO `employee` VALUES (1019, '陈伟', '男', '资深软件工程师', '1979-11-05');
INSERT INTO `employee` VALUES (1020, '杨丽', '女', '初级行政专员', '1996-02-20');
INSERT INTO `employee` VALUES (1021, '李伟', '男', '高级数据科学家', '1984-07-10');
INSERT INTO `employee` VALUES (1022, '张丽', '女', '资深前端工程师', '1986-01-18');
INSERT INTO `employee` VALUES (1023, '赵伟', '男', '初级后端工程师', '1997-05-25');
INSERT INTO `employee` VALUES (1024, '孙丽', '女', '高级UI/UX设计师', '1983-09-30');
INSERT INTO `employee` VALUES (1025, '周伟', '男', '资深产品经理', '1980-03-15');
INSERT INTO `employee` VALUES (1026, '吴丽', '女', '初级数据分析师', '1995-07-20');
INSERT INTO `employee` VALUES (1027, '郑伟', '男', '高级技术顾问', '1981-10-01');
INSERT INTO `employee` VALUES (1028, '王丽', '女', '资深市场专员', '1985-04-15');
INSERT INTO `employee` VALUES (1029, '刘伟', '男', '初级程序员', '1998-08-10');
INSERT INTO `employee` VALUES (1030, '陈丽', '女', '高级人力资源经理', '1987-02-28');
INSERT INTO `employee` VALUES (1031, '杨伟', '男', '资深运维工程师', '1979-06-20');
INSERT INTO `employee` VALUES (1032, '李丽', '女', '初级文案策划', '1996-01-12');
INSERT INTO `employee` VALUES (1033, '张伟', '男', '高级销售代表', '1984-09-05');
INSERT INTO `employee` VALUES (1034, '赵丽', '女', '资深法律顾问', '1986-03-18');
INSERT INTO `employee` VALUES (1035, '孙伟', '男', '初级技术支持', '1997-07-25');
INSERT INTO `employee` VALUES (1036, '周丽', '女', '高级市场分析师', '1983-11-30');
INSERT INTO `employee` VALUES (1037, '吴伟', '男', '资深软件工程师', '1980-05-10');
INSERT INTO `employee` VALUES (1038, '郑丽', '女', '初级行政专员', '1995-09-12');
INSERT INTO `employee` VALUES (1039, '王伟', '男', '高级数据科学家', '1981-08-05');
INSERT INTO `employee` VALUES (1040, '刘丽', '女', '资深前端工程师', '1987-02-18');
INSERT INTO `employee` VALUES (1041, '陈伟', '男', '初级后端工程师', '1998-04-20');
INSERT INTO `employee` VALUES (1042, '杨丽', '女', '高级UI/UX设计师', '1984-10-30');
INSERT INTO `employee` VALUES (1043, '李伟', '男', '资深产品经理', '1980-06-15');
INSERT INTO `employee` VALUES (1044, '张丽', '女', '初级数据分析师', '1996-08-10');
INSERT INTO `employee` VALUES (1045, '赵伟', '男', '高级技术顾问', '1981-12-01');
INSERT INTO `employee` VALUES (1046, '孙丽', '女', '资深市场专员', '1985-05-15');
INSERT INTO `employee` VALUES (1047, '周伟', '男', '初级程序员', '1998-09-20');
INSERT INTO `employee` VALUES (1048, '吴丽', '女', '高级人力资源经理', '1987-03-28');
INSERT INTO `employee` VALUES (1049, '郑伟', '男', '资深运维工程师', '1979-07-20');
INSERT INTO `employee` VALUES (1050, '王丽', '女', '初级文案策划', '1996-02-12');
INSERT INTO `employee` VALUES (1051, '刘伟', '男', '高级销售代表', '1984-10-05');
INSERT INTO `employee` VALUES (1052, '陈丽', '女', '资深法律顾问', '1986-04-18');
INSERT INTO `employee` VALUES (1053, '杨伟', '男', '初级技术支持', '1997-08-25');
INSERT INTO `employee` VALUES (1054, '李丽', '女', '高级市场分析师', '1983-12-30');
INSERT INTO `employee` VALUES (1055, '张伟', '男', '资深软件工程师', '1980-07-10');
INSERT INTO `employee` VALUES (1056, '赵丽', '女', '初级行政专员', '1995-10-12');
INSERT INTO employee VALUES (1057, '孙伟', '男', '高级数据科学家', '1981-09-05');
INSERT INTO employee VALUES (1058, '周丽', '女', '资深前端工程师', '1987-03-18');
INSERT INTO employee VALUES (1059, '吴伟', '男', '初级后端工程师', '1998-05-20');
INSERT INTO employee VALUES (1060, '郑丽', '女', '高级UI/UX设计师', '1984-11-30');
INSERT INTO employee VALUES (1061, '王伟', '男', '资深产品经理', '1980-08-15');
INSERT INTO employee VALUES (1062, '刘丽', '女', '初级数据分析师', '1996-09-10');
INSERT INTO employee VALUES (1063, '陈伟', '男', '高级技术顾问', '1981-10-01');
INSERT INTO employee VALUES (1064, '杨丽', '女', '资深市场专员', '1985-06-15');
INSERT INTO employee VALUES (1065, '李伟', '男', '初级程序员', '1998-10-20');
INSERT INTO employee VALUES (1066, '张丽', '女', '高级人力资源经理', '1987-04-28');
INSERT INTO employee VALUES (1067, '赵伟', '男', '资深运维工程师', '1979-08-20');
INSERT INTO employee VALUES (1068, '孙丽', '女', '初级文案策划', '1996-03-12');
INSERT INTO employee VALUES (1069, '周伟', '男', '高级销售代表', '1984-11-05');
INSERT INTO employee VALUES (1070, '吴丽', '女', '资深法律顾问', '1986-05-18');
INSERT INTO employee VALUES (1071, '郑伟', '男', '初级技术支持', '1997-09-25');
INSERT INTO employee VALUES (1072, '王丽', '女', '高级市场分析师', '1983-01-30');
INSERT INTO employee VALUES (1073, '刘伟', '男', '资深软件工程师', '1980-08-10');
INSERT INTO employee VALUES (1074, '陈丽', '女', '初级行政专员', '1995-11-12');
INSERT INTO employee VALUES (1075, '杨伟', '男', '高级数据科学家', '1981-10-05');
INSERT INTO employee VALUES (1076, '李丽', '女', '资深前端工程师', '1987-04-18');
INSERT INTO employee VALUES (1077, '张伟', '男', '初级后端工程师', '1998-06-20');
INSERT INTO employee VALUES (1078, '赵丽', '女', '高级UI/UX设计师', '1984-12-30');
INSERT INTO employee VALUES (1079, '孙伟', '男', '资深产品经理', '1980-09-15');
INSERT INTO employee VALUES (1080, '周丽', '女', '初级数据分析师', '1996-10-10');
INSERT INTO employee VALUES (1081, '吴伟', '男', '高级技术顾问', '1981-11-01');
INSERT INTO employee VALUES (1082, '郑丽', '女', '资深市场专员', '1985-07-15');
INSERT INTO employee VALUES (1083, '王伟', '男', '初级程序员', '1998-11-20');
INSERT INTO employee VALUES (1084, '刘丽', '女', '高级人力资源经理', '1987-05-28');
INSERT INTO employee VALUES (1085, '陈伟', '男', '资深运维工程师', '1979-09-20');
INSERT INTO employee VALUES (1086, '杨丽', '女', '初级文案策划', '1996-04-12');
INSERT INTO employee VALUES (1087, '李伟', '男', '高级销售代表', '1984-12-05');
INSERT INTO employee VALUES (1088, '张丽', '女', '资深法律顾问', '1986-06-18');
INSERT INTO employee VALUES (1089, '赵伟', '男', '初级技术支持', '1997-10-25');
INSERT INTO employee VALUES (1090, '孙丽', '女', '高级市场分析师', '1983-02-30');
INSERT INTO employee VALUES (1091, '周伟', '男', '资深软件工程师', '1980-09-10');
INSERT INTO employee VALUES (1092, '吴丽', '女', '初级行政专员', '1995-12-12');
INSERT INTO employee VALUES (1093, '郑伟', '男', '高级数据科学家', '1981-11-05');
INSERT INTO employee VALUES (1094, '王丽', '女', '资深前端工程师', '1987-05-18');
INSERT INTO employee VALUES (1095, '刘伟', '男', '初级后端工程师', '1998-07-20');
INSERT INTO employee VALUES (1096, '陈丽', '女', '高级UI/UX设计师', '1984-01-30');
INSERT INTO employee VALUES (1097, '杨伟', '男', '资深产品经理', '1980-10-15');
INSERT INTO employee VALUES (1098, '李丽', '女', '初级数据分析师', '1996-11-10');
INSERT INTO employee VALUES (1099, '张伟', '男', '高级技术顾问', '1981-12-01');
INSERT INTO employee VALUES (1100, '赵丽', '女', '资深市场专员', '1985-08-15');

1.8添加批量删除

控制层:

位置:src/main/java/com/cdp/zwy/zwy_manager_back_v1/controller/EmployeeController.java

java 复制代码
    @DeleteMapping("/deleteBatch")
    public Result deleteBatch(@RequestBody List<Integer> ids){
        return Result.success(employeeService.deleteBatch(ids));
    }

业务层:

位置:src/main/java/com/cdp/zwy/zwy_manager_back_v1/service/EmployeeService.java

java 复制代码
    public int deleteBatch(List<Integer> ids) {
        int rows = 0;
        for (Integer id : ids) {
            Employee employee = employeeMapper.selectById(id);
            if (employee == null){
                throw new EmployeeServiceException(ErrorCode.EMPLOYEE_NOT_FOUND);
            }
            int row =  employeeMapper.deleteById(id);
            if(row!=1){
                throw new EmployeeServiceException(ErrorCode.EMPLOYEE_DELETE_ERROR);
            }
            rows++;
        }
      return rows;
    }

测试

2.前端项目

2.1项目创建

2.1.1使用cmd创建vue项目

在文件资源管理器中打开你想创建位置路径

复制代码
npm create vue@latest

选择只选择Route

依次执行以下命令

访问搭建好的vue项目

2.1.2瘦身vue项目

idea打开该项目,项目原始结构如下

瘦身后的项目结构

修改3个文件添加1个文件

名称:App.vue

位置:src/App.vue

html 复制代码
<template>
 <RouterView/>
</template>

名称:main.js

位置:src/main.js

html 复制代码
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'

const app = createApp(App)

app.use(router)

app.mount('#app')

名称:HelloWorld.vue

位置:src/views/HelloWorld.vue

html 复制代码
<template>
  <div>
    <h1>Hello World</h1>
  </div>
</template>
<script setup>

</script>

名称:index.js

位置:src/router/index.js

html 复制代码
import { createRouter, createWebHistory } from 'vue-router'


const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path: '/',
      name: 'hello',
      component: () => import('../views/HelloWorld.vue'),
    },

  ],
})

export default router

2.1.3集成element-plus

下载element-plus依赖

复制代码
npm install element-plus@ 

package-lock.json或package.json或node_modules查看是否引入

配置element-plus

位置:src/main.js

名称:main.js

复制代码
 import ElementPlus from 'element-plus'
    import 'element-plus/dist/index.css'

  app.use(ElementPlus)

测试element-plus是否配置好

新建视图

位置:src/views/Button.vue

名称:Button.vue

html 复制代码
<template>
  <div>
    <el-button type="primary" @click="handleClick">按钮</el-button>
  </div>
</template>
<script setup>

</script>

添加路由

位置:src/router/index.js

名称:index.js

javascript 复制代码
    {
      path: '/button',
      name: 'button',
      component: () => import('../views/Button.vue'),
    }

访问该视图

2.2视图搭建

一共有4个,404.vue,manager.vue,employeeOp.vue,home.vue

其中manager.vue(employeeOp.vue,home.vue) 是嵌套关系

404.vue是路由守卫

2.2.1 全局映入icon

位置:src/main.js

名称:main.js

复制代码
import * as ElementPlusIconsVue from '@element-plus/icons-vue'

for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
        app.component(key, component)
    }

2.2.2导入所需要的图片和样式

位置:src/assets/global.css

名称:global.css

css 复制代码
.card {

    margin-top: 20px;
    margin-left: 10px;
    padding: 10px;
    width: calc(100% - 40px);
    background-color: #ffffff;
    border: 1px solid #e4e7ed;
    border-radius: 4px;
    color: #303133;

}

位置:src/assets/img.png

名称:img.png

位置:/assets/404.png

名称:404.png

2.2.3视图文件编写

位置:src/view/employeeDataOp.vue

名称:employeeDataOp.vue

html 复制代码
<template>
  <div >
<!--    第一项 搜索框和重置按钮-->
    <div class="card">
      <el-input v-model="searchName" placeholder="请输入员工姓名" style="width: 200px;margin-right: 5px;" suffix-icon="Search"/>
      <el-button type="primary">搜索</el-button>
      <el-button type="warning">重置</el-button>
    </div>

<!--    第二项 常用操作 批量删除 添加员工-->
    <div class="card">
      <el-button type="primary">新建员工</el-button>
      <el-button type="danger">批量删除</el-button>
    </div>

<!--    第三项 员工数据表格-->
    <div class="card">
     <el-table :data = "data.tableData" height="400" style="width: 100%;border: #7a7575 solid 1px">
       <el-table-column prop="id" label="编号" />
       <el-table-column prop="name" label="姓名" />
       <el-table-column prop="gender" label="性别" />
       <el-table-column prop="title" label="职位" />
       <el-table-column prop="birthday" label="出生日期"/>

     </el-table>
    </div>

<!--    第四项 分页组件-->
    <div class="card">
      <el-pagination
          v-model:current-page="currentPage"
          v-model:page-size="pageSize"
          :page-sizes="[10, 20, 50, 100]"
          :small="small"
          :disabled="disabled"
          :background="background"
          layout="total, sizes, prev, pager, next, jumper"
          :total="400"

      />
    </div>
  </div>
</template>
<script setup>

import {reactive} from "vue";

const data =  reactive({
  tableData: [
    {
      id:1,
      name:'张三',
      gender:'男',
      title:'高级工程师',
      birthday:'1985-01-01'
    },

  ],


})
</script>

位置:src/veiws/home.vue

名称:home.vue

html 复制代码
<template>
  <div>
    员工管理系统首页
  </div>
</template>
<script setup>

</script>

位置:src/veiws/manager.vue

名称:manager.vue

html 复制代码
<template>
  <div>
<!--    顶部信息栏(logo 系统名 用户头像 用户名)开始 -->
    <div style="height: 40px;background-color: aqua;display:flex;align-items:center;
">
      <img src="../assets/img.png" style="width: 40px;margin-left: 20px">
      <span style="margin-left: 10px;font-size: 20px;font-family: 新宋体;color: white">员工管理系统</span>
      <div style="flex:1"></div>

      <el-avatar  src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"/>
      <span style="margin-left: 10px;margin-right:10px;font-size: 20px;font-family: 新宋体;color: white">泳</span>

    </div>
    <!--    顶部信息栏(logo 系统名 用户头像 用户名)结束 -->

<!--    body部分开始-->
    <div style="display: flex">
<!--    左边导航栏开始-->
      <div style="width: 140px;height: calc(100vh - 40px);border-right: #cdcdcd solid 1px">
        <el-menu
            router>
          <el-menu-item index="/manager/home" >
            <el-icon>
              <HomeFilled />
            </el-icon>
              <span>首页</span>
          </el-menu-item>
          <el-menu-item index="/manager/employeeDataOp">
            <el-icon><User /></el-icon>
              <span>员工管理</span>
          </el-menu-item>
        </el-menu>

      </div>
<!--    左边导航栏结束-->

<!--    右边数据域开始-->
      <div style="width: calc(100% - 140px)">
        <RouterView/>
      </div>
<!--    右边数据域结束-->
    </div>
<!--    body部分结束-->





  </div>
</template>
<script setup>

</script>

位置:src/view/404.vue

名称:404.vue

html 复制代码
<template>

    <div class="card" style="display:flex;align-items:center;">
      <img src="@/assets/404.png" style="width: 100%;">
      </div>
  <div style="margin-top: 20px;">
    <div style="text-align: center;">
      <el-button type="primary" @click="backLatestPage">返回上一页</el-button>
    </div>
  </div>


</template>
<script setup>
import { useRouter } from 'vue-router'
const router = useRouter()
const backLatestPage = () => {
  router.go(-1)
}

</script>

2.2.4路由修改

位置:src/router/index.js

名称:index.js

javascript 复制代码
import { createRouter, createWebHistory } from 'vue-router'


const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path: '/',
      name: 'hello',
      component: () => import('../views/HelloWorld.vue'),
    },
    {
      path: '/button',
      name: 'button',
      component: () => import('../views/Button.vue'),
    },
    {
      path:'/manager',
      name:'manager',
      component:()=>import('../views/Manager.vue'),
      children:[
        {
          path:'/manager/employeeDataOp',
          name:'employeeDataOp',
          meta:{title:'员工数据操作'},
          component:()=>import('../views/employeeDataOp.vue')
        },
          {
            path:'/manager/home',
            name:'home',
            meta:{title:'首页'},
            component:()=>import('../views/home.vue')
          }
      ]
    },
    {
      path:'/404',
      name:'404',
      meta:{title:'404'},
      component:()=>import('../views/404.vue')

    },
    {
      path:'/:pathMatch(.*)*',
      redirect:'/404',

    }

  ],
})
router.beforeEach((to,from,next)=>{
    document.title=to.meta.title;
    next()
})

export default router

2.2.4静态界面展示

2.3接口调用

2.3.1安装axios(发请求的工具)

复制代码
 npm install axios@latest

2.3.2编写request.js文件(处理请求)

位置:src/utils/request.js

javascript 复制代码
const request  =  axios.create({
    baseURL:'http://localhost:9999',//后台接口地址
    timeout:5000 //请求超时设置
})

//request 拦截器
// 可以自请求发送前对请求做一些处理
request.interceptors.request.use(config => {
    config.headers['Content-Type'] = 'application/json;charset=utf-8';
    return config
},error => {
    return Promise.reject(error)

});
//可以在接口响应后统一处理结果
request.interceptors.response.use(
    response =>{
        let res = response.data;
    //     兼容服务器端返回的字符串数据
        if(typeof res === 'string') {
            res = res ?   JSON.parse(res) : res
        }
        return res;
    },
    error => {
        if(error.response.status === 404){
            ElMessage.error('服务器未找到该接口')
        }else if(error.response.status === 500){
            ElMessage.error('服务器内部错误')
        }else{
            console.error(error.message)
        }
        return Promise.reject(error)
    }
)
export default request

2.3.3修改employeeDataOp.vue

位置:src/views/employeeDataOp.vue

html 复制代码
<template>
  <div >
<!--    第一项 搜索框和重置按钮-->
    <div class="card">
      <el-input v-model="data.searchName" placeholder="请输入员工姓名" style="width: 200px;margin-right: 5px;" suffix-icon="Search"/>
      <el-button type="primary" @click="loadData()">搜索</el-button>
      <el-button type="warning" @click="reset()">重置</el-button>
    </div>

<!--    第二项 常用操作 批量删除 添加员工-->
    <div class="card">
      <el-button type="primary" @click="switchAddDialog">新建员工</el-button>
      <el-button type="danger" @click="deleteBatchMessageBox">批量删除</el-button>
    </div>

<!--    第三项 员工数据表格-->
    <div class="card">
     <el-table @selectionChange="handleSelectionChange" :data = "data.tableData" height="400" style="width: 100%;border: #7a7575 solid 1px">
       <el-table-column type="selection" width="55" />
       <el-table-column prop="id" label="编号" />
       <el-table-column prop="name" label="姓名" />
       <el-table-column prop="gender" label="性别" />
       <el-table-column prop="title" label="职位" />
       <el-table-column prop="birthday" label="出生日期"/>
       <el-table-column fixed="right" label="操作" width="120">
         <template #default="scope">
           <el-button  type="primary"  @click="editRow(scope.row)" circle>
             <el-icon><Edit /></el-icon>
           </el-button>
           <el-button  type="danger" @click="deleteMessageBox(scope.row)" circle>
             <el-icon><Delete /></el-icon>
           </el-button>
         </template>
       </el-table-column>

     </el-table>
    </div>

<!--    第四项 分页组件-->
    <div class="card">
      <el-pagination

          v-model:current-page="data.currentPage"
          v-model:page-size="data.pageSize"
          @current-change="loadData"
          @size-change="loadData"
          :page-sizes="[10, 20, 50, 100]"

          layout="total, sizes, prev, pager, next, jumper"
          v-model:total="data.total"

      />
    </div>
    <el-dialog
        v-model="data.AddDialogVisible"
        title="新建员工"
        width="300"
        align-center
    >
      <el-input v-model="data.employee.name" style="width: 240px;margin-bottom: 20px;" placeholder="请输入名称"></el-input>
      <el-radio-group v-model="data.employee.gender" style="width: 240px;margin-bottom: 20px;">
        <el-radio value="男" size="large" border>男</el-radio>
        <el-radio value="女" size="large" border>女</el-radio>
      </el-radio-group>
      <el-input v-model="data.employee.title" style="width: 240px;margin-bottom: 20px;" placeholder="请输入职称"></el-input>


        <el-date-picker
            v-model="data.employee.birthday"
            type="date"
            placeholder="选择出生日期"
            format="YYYY-MM-DD"
            value-format="YYYY-MM-DD"

        />
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="switchAddDialog">取消</el-button>
          <el-button type="primary" @click="save()">
            确定
          </el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>

import {reactive,ref} from "vue";
import request from "@/utils/request.js";

import {ElMessage,ElMessageBox} from "element-plus";

const res = ref();
const data =  reactive({
  AddDialogVisible:false,
  tableData: [
  ],
  currentPage:1,
  pageSize:5,
  searchName:'',
  employee:{
    id:0,
    name:'',
    gender:'',
    title:'',
    birthday:''
  },
  ids:[]

})
const loadData = () => {


  const loadAll = () =>{

        request.get('employee/selectPage', {
          params: {
            pageNum: data.currentPage,
            pageSize: data.pageSize,
          }
        }).then(res=> {
          data.tableData = res.data.list;
          data.total = res.data.total;

          console.log(res.data.list)
        })
      }
      const loadByName = () =>{
        request.post('employee/findByName',{
            name:data.searchName,
        },{  params: {
                pageNum: data.currentPage,
                pageSize: data.pageSize,
              }}).then(res=>{
          data.tableData = res.data.list;
          data.total = res.data.total;
          console.log(res.data.list)
        })
        }
  data.searchName ? loadByName() :loadAll()
}
loadData();
const reset = () =>{
  data.searchName = '';
  loadData();
}
const switchAddDialog = () =>{
  data.AddDialogVisible = data.AddDialogVisible ? false : true;
}
const editRow = (row) =>{
  data.employee = row;
  switchAddDialog();
  //深拷贝,解决就算取消修改,数据还是被修改了的问题
  data.employee = JSON.parse(JSON.stringify(row));

}
const save = () =>{
  const update = () =>{
    request.put('employee/modify',data.employee).then(res=>{
      console.log(res);
      if(res.code === '200'){
        ElMessage.success('添加成功');
        loadData();
        switchAddDialog();
      }else {
        ElMessage.error(res.code + '/n' + res.msg);
      }
    })
  }
  const add = () =>{
    request.post('employee/add',data.employee).then(res=>{
      console.log(res);
      if(res.code === '200'){
        ElMessage.success('添加成功');
        loadData();
        switchAddDialog();
      }else {
        ElMessage.error(res.code + '/n' + res.msg);
      }
    })
  }
  data.employee.id != 0 ? update() : add();
}
const deleteOne = (row) =>{
  request.delete(`employee/deleteById/${row.id}`).then(res=>{
    if(res.code === '200'){
      ElMessage.success('删除成功');
      loadData();
    }else {
      ElMessage.error(res.code + '/n' + res.msg);
    }
  })
}
const handleSelectionChange = (rows) =>{
  data.ids = rows.map(row => row.id);
  console.log(data.ids);
}
const deleteBatch = () =>{
  request.delete(`employee/deleteBatch`,{data:data.ids}).then(res=>{
    if(res.code === '200'){
      ElMessage.success('批量删除成功');
      loadData();
    }else {
      ElMessage.error(res.code + '/n' + res.msg);
    }

  })
}
const deleteMessageBox = (row) =>{
  ElMessageBox.confirm('此操作将永久删除该信息, 是否继续?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'danger',
  }).then(() => {
    deleteOne(row);
  }).catch(() => {
    ElMessage({
      type: 'info',
      message: '已取消删除',
    });
  });
}
const deleteBatchMessageBox = () =>{
  if(data.ids.length === 0){
    ElMessage.error('请选择要删除的数据');
    return;
  }
  ElMessageBox.confirm('此操作将永久删除该信息, 是否继续?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'danger',
  }).then(() => {
    deleteBatch();
  }).catch(() => {
    ElMessage({
      type: 'info',
      message: '已取消删除',
    });
  });
}
</script>

我来解释也哈这个视图,

静态内容方面

分为四个部分对应代码四个<div>

第一个是搜索框

第二个是一些基础操作

第三个是表格

第四个是分页组件

还有一个对话框作用是添加或修改员工信息点击新建按钮这个对话框显示对应代码<el_dialog>标签

还有一个消息框当,进行删除操作时候提供一个缓冲,以免误删对应const deleteMassageBox,deleteBatchMassageBox.

相关推荐
沃野_juededa5 分钟前
uniapp自定义选项卡
java·前端·javascript
问道飞鱼1 小时前
【springboot知识】配置方式实现SpringCloudGateway相关功能
java·spring boot·后端·gateway
樽酒ﻬق1 小时前
打造美观 API 文档:Spring Boot + Swagger 实战指南
java·spring boot·后端
碎梦归途2 小时前
23种设计模式-行为型模式之中介者模式(Java版本)
java·jvm·设计模式·中介者模式·软件设计师
Java手札2 小时前
在idea开发中遇到的20个bug
java·bug·intellij-idea
南客先生2 小时前
Arthas在Java程序监控和分析中的应用
java·面试·arthas
小红的布丁2 小时前
JVM 内存分配策略
java·jvm
m0_555762902 小时前
vscode 配置qt
ide·vscode·qt
缘来的精彩3 小时前
Android Studio 中实现方法和参数显示一行
android·ide·android studio
赶路人儿3 小时前
mybatis传递多个不同类型的参数到mapper xml文件
java·mybatis