这个员工信息管理系统是典型的毕业设计选题,涵盖了企业信息化管理的基础需求。我在大三暑期实习时第一次接触这类系统,当时为本地一家中小型企业开发了类似的解决方案。后来在指导学弟学妹毕业设计时,发现这个选题既能展示完整的技术栈应用,又容易找到真实需求场景。
选择Java+Spring Boot+MySQL的技术组合有几个实际考量:首先这是企业级开发的主流技术栈,其次Spring Boot的自动化配置能大幅降低环境搭建复杂度,最后MySQL作为关系型数据库能很好支撑CRUD操作。整套系统开发下来,学生可以掌握从需求分析到部署上线的完整流程。
采用经典的三层架构时,我建议在Controller和Service层之间增加DTO(Data Transfer Object)。比如员工信息查询接口,数据库返回的Employee实体可能包含薪资等敏感字段,通过EmployeeDTO可以只暴露必要信息。具体实现:
java复制// Controller层
@GetMapping("/employees")
public List<EmployeeDTO> getAllEmployees() {
return employeeService.getAllEmployees();
}
// Service层
public List<EmployeeDTO> getAllEmployees() {
return employeeRepository.findAll()
.stream()
.map(this::convertToDTO)
.collect(Collectors.toList());
}
private EmployeeDTO convertToDTO(Employee employee) {
// 只暴露非敏感字段
}
MySQL表设计最常见的坑是字段类型选择。比如:
建表示例:
sql复制CREATE TABLE employee (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
phone VARCHAR(20),
hire_date DATE,
salary DECIMAL(10,2),
department_id INT,
INDEX idx_department (department_id)
);
使用Spring Data JPA时,注意这几个实践技巧:
java复制// 正确示例
List<Employee> findByDepartment_NameAndHireDateAfter(String departmentName, Date hireDate);
// 错误示例 - 方法名太长且不符合规范
List<Employee> findEmployeesByDepartmentNameAndAfterHireDate(...);
properties复制# application.properties
spring.jpa.properties.hibernate.jdbc.batch_size=50
spring.jpa.properties.hibernate.order_inserts=true
前端分页常见性能问题可以通过后端分页解决:
java复制@GetMapping("/employees")
public Page<EmployeeDTO> getEmployeesByPage(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size) {
Pageable pageable = PageRequest.of(page, size, Sort.by("name"));
return employeeService.getAllEmployees(pageable);
}
配合前端使用Element UI的分页组件:
html复制<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage"
:page-sizes="[10, 20, 50]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next"
:total="total">
</el-pagination>
当查询员工及其部门信息时,如果没有正确配置关联关系,会导致多次查询:
java复制// 错误做法 - 会产生N+1查询
@OneToMany(mappedBy = "department")
private List<Employee> employees;
// 正确做法 - 使用JOIN FETCH
@Query("SELECT d FROM Department d JOIN FETCH d.employees WHERE d.id = :id")
Department findByIdWithEmployees(@Param("id") Long id);
新手常犯的事务错误包括:
正确示例:
java复制@Service
public class EmployeeService {
@Transactional(rollbackFor = Exception.class)
public void updateEmployeeWithDepartment(Employee employee, Department department) {
departmentRepository.save(department);
employee.setDepartment(department);
employeeRepository.save(employee);
// 模拟业务异常
if (employee.getSalary() < 0) {
throw new IllegalArgumentException("薪资不能为负数");
}
}
}
使用Spring Profile管理不同环境配置:
properties复制# application-dev.properties
spring.datasource.url=jdbc:mysql://localhost:3306/employee_dev
spring.jpa.hibernate.ddl-auto=update
# application-prod.properties
spring.datasource.url=jdbc:mysql://prod-db:3306/employee_prod
spring.jpa.hibernate.ddl-auto=validate
启动时指定环境:
bash复制java -jar employee-management.jar --spring.profiles.active=prod
Tomcat JDBC连接池推荐配置:
properties复制spring.datasource.tomcat.initial-size=5
spring.datasource.tomcat.max-active=20
spring.datasource.tomcat.max-idle=10
spring.datasource.tomcat.min-idle=5
spring.datasource.tomcat.test-while-idle=true
spring.datasource.tomcat.validation-query=SELECT 1
如果想提升项目竞争力,可以考虑:
java复制@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("com.example.employee"))
.paths(PathSelectors.any())
.build();
}
}
java复制@Cacheable(value = "employees", key = "#id")
public EmployeeDTO getEmployeeById(Long id) {
return employeeRepository.findById(id)
.map(this::convertToDTO)
.orElseThrow(() -> new ResourceNotFoundException("Employee not found"));
}
java复制@Aspect
@Component
public class LoggingAspect {
@AfterReturning(pointcut = "execution(* com.example.employee.service.*.*(..))",
returning = "result")
public void logServiceAccess(JoinPoint joinPoint, Object result) {
logger.info("执行: " + joinPoint.getSignature().getName());
logger.info("返回: " + result);
}
}
在实际开发中,我建议先用H2内存数据库快速原型开发,再迁移到MySQL。遇到复杂查询时,不妨试试JPA的Specification动态查询,它能保持代码的可读性。最后提醒,一定要写好单元测试,Mockito+JUnit5的组合能帮你省去很多调试时间。