1.设计数据库
/* Navicat Premium Data Transfer Source Server : localhost_3306 Source Server Type : MySQL Source Server Version : 80037 (8.0.37) Source Host : localhost:3306 Source Schema : studymysql Target Server Type : MySQL Target Server Version : 80037 (8.0.37) File Encoding : 65001 Date: 24/12/2024 11:32:08 */ SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for emp -- ---------------------------- DROP TABLE IF EXISTS `emp`; CREATE TABLE `emp` ( `empno` int NOT NULL AUTO_INCREMENT COMMENT '雇员编号', `ename` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '雇员姓名', `job` varchar(9) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '表示工作职位', `mgr` int NULL DEFAULT NULL COMMENT '表示一个雇员的领导编号', `hiredate` datetime NULL DEFAULT NULL COMMENT '表示雇佣日期', `sal` double NULL DEFAULT NULL COMMENT '表示月薪,工资', `comm` double NULL DEFAULT NULL COMMENT '表示奖金或佣金', `deptno` int NULL DEFAULT NULL, PRIMARY KEY (`empno`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of emp -- ---------------------------- SET FOREIGN_KEY_CHECKS = 1;
2.编写实体类和数据库形成映射
package com.pyb.pojo;
/**
* @version 1.0
* @Author 彭彦彬
* @Date 2024/12/24 15:07
* @注释
*/
public class Emp {
private int empNo;
private String eName;
private String job;
private int mgr;
private String hireDate;
private double sal;
private double comm;
private int deptNo;
public Emp(int empNo, String eName, String job, int mgr, String hireDate, double sal, double comm, int deptNo) {
this.empNo = empNo;
this.eName = eName;
this.job = job;
this.mgr = mgr;
this.hireDate = hireDate;
this.sal = sal;
this.comm = comm;
this.deptNo = deptNo;
}
public Emp(String eName, String job) {
this.eName = eName;
this.job = job;
}
public Emp(String eName, String job, int mgr, String hireDate, double sal, int deptNo, double comm) {
this.eName = eName;
this.job = job;
this.mgr = mgr;
this.hireDate = hireDate;
this.sal = sal;
this.deptNo = deptNo;
this.comm = comm;
}
@Override
public String toString() {
return "Emp{" +
"empNo=" + empNo +
", eName='" + eName + '\'' +
", job='" + job + '\'' +
", mgr=" + mgr +
", hireDate='" + hireDate + '\'' +
", sal=" + sal +
", comm=" + comm +
", deptNo=" + deptNo +
'}';
}
public Emp() {
}
public int getEmpNo() {
return empNo;
}
public void setEmpNo(int empNo) {
this.empNo = empNo;
}
public String geteName() {
return eName;
}
public void seteName(String eName) {
this.eName = eName;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
public int getMgr() {
return mgr;
}
public void setMgr(int mgr) {
this.mgr = mgr;
}
public String getHireDate() {
return hireDate;
}
public void setHireDate(String hireDate) {
this.hireDate = hireDate;
}
public double getSal() {
return sal;
}
public void setSal(double sal) {
this.sal = sal;
}
public double getComm() {
return comm;
}
public void setComm(double comm) {
this.comm = comm;
}
public int getDeptNo() {
return deptNo;
}
public void setDeptNo(int deptNo) {
this.deptNo = deptNo;
}
}
3.编写数据和Java代码交互逻辑
-
定义业务接口
package com.pyb.dao;
import com.pyb.pojo.Emp;
import java.sql.SQLException;
import java.util.List;
/**
* @version 1.0
* @Author 彭彦彬
* @Date 2024/12/25 10:17
* @注释
*/
public interface EmpDao {
/**
* 获取所有用户数据
* @return
*/
List<Emp> list() throws SQLException;
/**
* 查询员工信息通过姓名
* @param name
* @return
*/
Emp selectEmpByName(String name) throws SQLException;
/**
* 添加員工信息
* @param emp
*/
int addEmp(Emp emp);
int deleteEmp(Emp emp);
List<Emp> selectEmpByLike(Emp emp,int page,int limit);
long countEmpByLike(Emp emp);
}
-
实现业务接口
package com.pyb.dao.daoImpl;
import com.pyb.dao.EmpDao;
import com.pyb.pojo.Emp;
import com.pyb.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/**
* @version 1.0
* @Author 彭彦彬
* @Date 2024/12/25 10:19
*/
public class EmpDaoImpl implements EmpDao {
@Override
public List<Emp> list() throws SQLException {
String sql = "SELECT * FROM emp";
List<Emp> list = new ArrayList<>();
// 使用 try-with-resources 确保资源自动关闭
try (Connection con = JdbcUtils.getConnection();
PreparedStatement ps = con.prepareStatement(sql);
ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
int empno = rs.getInt("empno");
String ename = rs.getString("ename");
String job = rs.getString("job");
int mgr = rs.getInt("mgr");
String hiredate = rs.getString("hiredate"); // 如果 hiredate 是日期类型
double sal = rs.getDouble("sal");
double comm = rs.getDouble("comm");
int deptno = rs.getInt("deptno");
list.add(new Emp(empno, ename, job, mgr, hiredate, sal, comm, deptno));
}
} catch (SQLException e) {
// 记录详细的错误信息,以便于调试
e.printStackTrace(); // 在实际应用中应使用日志框架如 SLF4J 等记录错误信息
throw e; // 或者抛出自定义异常
}
return list;
}
@Override
public Emp selectEmpByName(String name) throws SQLException {
String sql = "SELECT * FROM emp WHERE ename = ?";
// 使用 try-with-resources 确保资源自动关闭
try (Connection con = JdbcUtils.getConnection();
PreparedStatement ps = con.prepareStatement(sql)) {
ps.setString(1, name);
try (ResultSet rs = ps.executeQuery()) {
if (rs.next()) {
int empno = rs.getInt("empno");
String ename = rs.getString("ename");
String job = rs.getString("job");
int mgr = rs.getInt("mgr");
String hiredate = rs.getString("hiredate"); // 如果 hiredate 是日期类型
double sal = rs.getDouble("sal");
double comm = rs.getDouble("comm");
int deptno = rs.getInt("deptno");
return new Emp(empno, ename, job, mgr, hiredate, sal, comm, deptno);
}
}
// 如果没有找到员工,则返回 null
return null;
} catch (SQLException e) {
// 记录详细的错误信息,以便于调试
e.printStackTrace(); // 在实际应用中应使用日志框架如 SLF4J 等记录错误信息
throw e; // 或者抛出自定义异常
}
}
@Override
public int addEmp(Emp emp) {
String sql="insert into emp(ename,job,mgr,hiredate,sal,comm,deptno)values(?,?,?,?,?,?,?)";
int effect=0;
// 使用 try-with-resources 确保资源自动关闭
try (Connection con = JdbcUtils.getConnection();
PreparedStatement ps = con.prepareStatement(sql)) {
ps.setString(1,emp.geteName());
ps.setString(2,emp.getJob());
ps.setInt(3,emp.getMgr());
ps.setString(4,emp.getHireDate());
ps.setDouble(5, emp.getSal());
ps.setDouble(6,emp.getComm());
ps.setInt(7,emp.getDeptNo());
effect=ps.executeUpdate();
} catch (SQLException e) {
// 记录详细的错误信息,以便于调试
e.printStackTrace(); // 在实际应用中应使用日志框架如 SLF4J 等记录错误信息
}
return effect;
}
@Override
public int deleteEmp(Emp emp) {
String sql = "DELETE FROM emp WHERE empno = ?";
int affectedRows = 0;
// 使用 try-with-resources 确保资源自动关闭
try (Connection con = JdbcUtils.getConnection();
PreparedStatement ps = con.prepareStatement(sql)) {
ps.setInt(1, emp.getEmpNo());
affectedRows = ps.executeUpdate();
if (affectedRows == 0) {
System.out.println("Warning: No rows were deleted for empno=" + emp.getEmpNo());
// 可选择抛出自定义异常或返回特定值以表示未找到要删除的记录
} else {
System.out.println("Employee with empno=" + emp.getEmpNo() + " deleted successfully.");
}
} catch (SQLException e) {
// 记录详细的错误信息,以便于调试
e.printStackTrace(); // 在实际应用中应使用日志框架如 SLF4J 等记录错误信息
// 抛出自定义异常或进行其他适当的错误处理
throw new RuntimeException("Database error occurred while deleting employee.", e);
}
return affectedRows;
}
@Override
public List<Emp> selectEmpByLike(Emp emp, int page, int limit) {
// Adjust the SQL query to support pagination using LIMIT and OFFSET
String sql = "SELECT * FROM emp WHERE ename LIKE ? OR job LIKE ? LIMIT ? OFFSET ?";
List<Emp> list = new ArrayList<>();
try (Connection con = JdbcUtils.getConnection();
PreparedStatement ps = con.prepareStatement(sql)) {
// Set parameters with wildcards for the LIKE clause
ps.setString(1, "%" + emp.geteName() + "%");
ps.setString(2, "%" + emp.getJob() + "%");
// Calculate offset based on page number and limit
int offset = (page - 1) * limit;
ps.setInt(3, limit);
ps.setInt(4, offset);
try (ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
int empno = rs.getInt("empno");
String ename = rs.getString("ename");
String job = rs.getString("job");
int mgr = rs.getInt("mgr");
String hiredate = rs.getString("hiredate"); // Assuming hiredate is a DATE type in database
double sal = rs.getDouble("sal");
Double comm = rs.getDouble("comm"); // Use Double to handle NULL values
int deptno = rs.getInt("deptno");
// Handle possible null values for comm
if (rs.wasNull()) {
comm = null;
}
list.add(new Emp(empno, ename, job, mgr, hiredate, sal, comm, deptno));
}
}
} catch (SQLException e) {
// Log the exception using a logging framework in production code
e.printStackTrace();
// You may want to throw or handle the exception here
}
return list; // Return the populated list
}
@Override
public long countEmpByLike(Emp emp) {
String sql = "SELECT COUNT(*) FROM emp WHERE ename LIKE ? OR job LIKE ?";
try (Connection con = JdbcUtils.getConnection();
PreparedStatement ps = con.prepareStatement(sql)) {
// Set parameters with wildcards for the LIKE clause
ps.setString(1, "%" + emp.geteName() + "%");
ps.setString(2, "%" + emp.getJob() + "%");
try (ResultSet rs = ps.executeQuery()) {
if (rs.next()) {
return rs.getLong(1);
}
}
} catch (SQLException e) {
// Log the exception using a logging framework in production code
e.printStackTrace();
}
return 0L;
}
}
-
编写服务层接口
package com.pyb.service;
/**
* @version 1.0
* @Author 彭彦彬
* @Date 2024/12/25 14:22
* @注释
*/
import com.pyb.pojo.Emp;
import java.sql.SQLException;
import java.util.List;
public interface EmpService {
List<Emp> selectEmpByLike(Emp emp, int page, int limit) throws SQLException;
long countEmpByLike(Emp emp) throws SQLException;
}
-
编写服务层实现类
package com.pyb.service.serviceImpl;
import com.pyb.dao.EmpDao;
import com.pyb.dao.daoImpl.EmpDaoImpl;
import com.pyb.pojo.Emp;
import com.pyb.service.EmpService;
import java.sql.SQLException;
import java.util.List;
public class EmpServiceImpl implements EmpService {
private final EmpDao empDao = new EmpDaoImpl();
@Override
public List<Emp> selectEmpByLike(Emp emp, int page, int limit) throws SQLException {
return empDao.selectEmpByLike(emp, page, limit);
}
@Override
public long countEmpByLike(Emp emp) throws SQLException {
return empDao.countEmpByLike(emp);
}
}
-
编写控制层实现页面控制
package com.pyb.controller;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.pyb.service.EmpService;
import com.pyb.pojo.Emp;
import com.pyb.service.serviceImpl.EmpServiceImpl;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@WebServlet("/api/likeEmp")
public class EmpLikeServlet extends HttpServlet {
private final EmpService empService = new EmpServiceImpl();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
handleRequest(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
handleRequest(req, resp);
}
private void handleRequest(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
// 处理请求编码
req.setCharacterEncoding("utf-8");
resp.setContentType("application/json;charset=UTF-8");
resp.setHeader("Access-Control-Allow-Origin", "*"); // 生产环境中应限制到具体域名
resp.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
resp.setHeader("Access-Control-Max-Age", "3600");
resp.setHeader("Access-Control-Allow-Headers", "Content-Type");
// 解析分页参数
int page = Integer.parseInt(req.getParameter("page") != null ? req.getParameter("page") : "1");
int limit = Integer.parseInt(req.getParameter("limit") != null ? req.getParameter("limit") : "2");
// 解析检索参数
String ename = req.getParameter("ename");
String job = req.getParameter("job");
// 调用Service层
List<Emp> list = empService.selectEmpByLike(new Emp(ename, job), page, limit);
long totalUsers = empService.countEmpByLike(new Emp(ename, job));
// 构建响应对象
Map<String, Object> responseData = new HashMap<>();
responseData.put("users", list);
responseData.put("total", totalUsers);
responseData.put("page", page);
responseData.put("limit", limit);
if (ename != null) responseData.put("ename", ename);
if (job != null) responseData.put("job", job);
ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(resp.getWriter(), responseData);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
启动服务部署到tomcat,用postman测试接口
http://localhost:8080/api/likeEmp?ename=a
-
测试结果

4.编写前端页面,实现前后端数据交互
-
html页面
<template> <div class="employee-manager"> <!-- 现有的表格和分页组件 --> <el-card class="box-card"> <template #header> <div class="card-header"> <span>员工列表</span> <!-- 检索框 --> <el-input v-model="searchEname" placeholder="请输入姓名" style="width: 200px; margin-right: 10px;"></el-input> <el-input v-model="searchJob" placeholder="请输入岗位" style="width: 200px; margin-right: 10px;"></el-input> <el-button type="primary" @click="fetchData">搜索</el-button> <el-button type="info" @click="resetSearch">重置</el-button> <el-button type="primary" @click="openAddEmployeeDialog">添加员工</el-button> </div> </template> <el-table :data="paginatedData" style="width: 100%; margin-top: 20px;" stripe> <el-table-column prop="empNo" label="ID" width="100" /> <el-table-column prop="eName" label="姓名" width="100" /> <el-table-column prop="job" label="岗位" width="100" /> <el-table-column prop="mgr" label="上级编号" /> <el-table-column prop="hireDate" label="入职日期" width="200"/> <el-table-column prop="sal" label="月薪" width="100"/> <el-table-column prop="comm" label="奖金" /> <el-table-column prop="deptNo" label="部门编号" /> <el-table-column fixed="right" label="操作" width="180"> <template #default="scope"> <el-button size="small" type="danger" @click="deleteEmployee(scope.row.empNo)">删除</el-button> </template> </el-table-column> </el-table> <el-pagination layout="total, sizes, prev, pager, next, jumper" :total="totalItems" :page-size="pageSize" :current-page="currentPage" @size-change="handleSizeChange" @current-change="handleCurrentChange" :page-sizes="[3, 6, 9, 12]" style="margin-top: 20px;" > </el-pagination> </el-card> <!-- 添加员工对话框 --> <el-dialog v-model="dialogVisible" title="添加员工" width="30%"> <el-form :model="employeeForm" label-width="100px" class="add-employee-form"> <el-form-item label="ID"> <el-input v-model="employeeForm.id" placeholder="请输入ID"></el-input> </el-form-item> <el-form-item label="姓名"> <el-input v-model="employeeForm.name" placeholder="请输入姓名"></el-input> </el-form-item> <el-form-item label="职位"> <el-input v-model="employeeForm.position" placeholder="请输入职位"></el-input> </el-form-item> </el-form> <template #footer> <span class="dialog-footer"> <el-button @click="closeDialog">取消</el-button> <el-button type="primary" @click="addEmployee">确认添加</el-button> </span> </template> </el-dialog> </div> </template>
-
css样式页面
<style scoped>
.employee-manager {
padding: 20px;
}
.box-card {
width: 100%;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.add-employee-form {
max-width: 400px;
margin: auto;
}
.el-table {
border-radius: 8px;
overflow: hidden;
}
.el-pagination {
text-align: center;
}
.dialog-footer {
text-align: right;
}
</style>
-
和后台交互的script代码
<script lang="js" setup>
import { ref, onMounted, computed } from 'vue';
import axios from 'axios';
import { ElMessage } from 'element-plus'; // 局部引入 ElMessage
const tableData = ref([]); // 使用 ref 创建响应式数据源
const totalItems = ref(0);
const currentPage = ref(1);
const pageSize = ref(3);
// 表单数据模型
const employeeForm = ref({
id: '',
name: '',
position: ''
});
// 对话框可见性
const dialogVisible = ref(false);
// 检索条件
const searchEname = ref('');
const searchJob = ref('');
// 计算属性,用于根据当前页码和每页大小获取分页后的数据
const paginatedData = computed(() => {
const start = (currentPage.value - 1) * pageSize.value;
const end = start + pageSize.value;
return tableData.value;
});
const fetchData = async () => {
try {
const response = await axios.get('http://localhost:8080/api/likeEmp', {
params: {
page: currentPage.value,
limit: pageSize.value,
ename: searchEname.value,
job: searchJob.value
}
});
const { users, total } = response.data;
tableData.value = users.map(user => ({ ...user, id: user.id, name: user.name, position: user.position }));
totalItems.value = total; // 更新总条目数
} catch (error) {
console.error('Error fetching data:', error);
}
};
onMounted(() => {
fetchData(); // 组件挂载时自动加载数据
});
const handleSizeChange = (newSize) => {
pageSize.value = newSize;
fetchData();
};
const handleCurrentChange = (newPage) => {
currentPage.value = newPage;
fetchData();
};
// 打开添加员工对话框的方法
const openAddEmployeeDialog = () => {
dialogVisible.value = true;
};
// 关闭对话框的方法
const closeDialog = () => {
dialogVisible.value = false;
Object.assign(employeeForm.value, {
id: '',
name: '',
position: ''
});
};
// 添加员工的方法
const addEmployee = async () => {
try {
const response = await axios.post('http://localhost:8080/api/emp', employeeForm.value, {
headers: {
'Content-Type': 'application/json'
}
});
console.log('Employee added successfully:', response.data);
// 关闭对话框并清空表单
closeDialog();
// 刷新表格数据
fetchData();
} catch (error) {
console.error('Error adding employee:', error);
}
};
// 删除员工的方法
const deleteEmployee = async (empNo) => {
try {
const response = await axios.delete(`http://localhost:8080/api/delEmp`, {
params: {
empNo: empNo
}
});
console.log('Employee deleted successfully:', response.data.message);
ElMessage({
message: response.data.message,
type: response.data.success ? 'success' : 'error'
});
// 刷新表格数据
fetchData();
} catch (error) {
console.error('Error deleting employee:', error);
ElMessage({
message: '删除员工时出错',
type: 'error'
});
}
};
// 重置检索条件的方法
const resetSearch = () => {
searchEname.value = '';
searchJob.value = '';
fetchData();
};
</script>
-
实现效果




















