☰
Java极简排课系统开发:Spring Boot与MySQL实战
2026/10/26 14:15:57 网站建设 项目流程

1. 项目概述:为什么需要极简排课系统?

在教练培训行业,排课一直是个让人头疼的问题。我见过太多培训机构还在用Excel手动排课,每次调整课表都要花上大半天时间,还经常出现教练时间冲突、教室资源重复预订的情况。更糟的是,有些机构甚至还在用纸质本子记录,一旦需要查询某位教练的课程安排,得翻半天记录本。

这套极简Java排课系统就是为了解决这些痛点而设计的。它采用Spring Boot + MyBatis技术栈,代码总量控制在2000行以内,但实现了教练管理、课程安排、冲突检测等核心功能。我在开发过程中特别注重"极简"二字——没有复杂的功能堆砌,所有设计都直指排课场景的实际需求。

提示:虽然市面上有现成的排课系统,但大多数要么功能过于复杂,要么价格昂贵。自己开发的好处是可以完全按照机构实际工作流程定制,后续维护和扩展也更灵活。

2. 系统架构与技术选型

2.1 为什么选择Java技术栈?

Java在企业级应用开发中有着不可替代的优势。首先,它的类型安全特性可以在编译期就发现很多潜在问题,这对排课系统这种对数据准确性要求高的场景特别重要。其次,Java生态中有大量成熟的框架和库,比如我们用的Spring Boot,可以快速搭建起稳定的后端服务。

我选择了以下技术组合:

  • 后端:Spring Boot 2.7 + MyBatis 3.5
  • 数据库:MySQL 8.0
  • 前端:Thymeleaf + Bootstrap 5(为了保持极简,没有用复杂的前端框架)
  • 构建工具:Maven

2.2 数据库设计要点

排课系统的核心是处理好三个实体间的关系:教练、课程和时间段。我的数据库设计主要包含以下表:

  1. coach表:存储教练基本信息

    CREATE TABLE `coach` ( `id` int NOT NULL AUTO_INCREMENT, `name` varchar(50) NOT NULL, `phone` varchar(20) DEFAULT NULL, `specialty` varchar(100) DEFAULT NULL, `status` tinyint DEFAULT '1' COMMENT '1-可用 0-不可用', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
  2. course表:课程定义

    CREATE TABLE `course` ( `id` int NOT NULL AUTO_INCREMENT, `name` varchar(100) NOT NULL, `duration` int DEFAULT '60' COMMENT '分钟数', `max_students` int DEFAULT '10', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
  3. schedule表:排课记录

    CREATE TABLE `schedule` ( `id` int NOT NULL AUTO_INCREMENT, `coach_id` int NOT NULL, `course_id` int NOT NULL, `start_time` datetime NOT NULL, `end_time` datetime NOT NULL, `classroom` varchar(50) DEFAULT NULL, PRIMARY KEY (`id`), KEY `idx_coach_time` (`coach_id`,`start_time`), KEY `idx_time` (`start_time`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

注意:schedule表上的联合索引特别重要,它能极大提升排课冲突检测的查询效率。我在实际测试中发现,没有这个索引时,检查某位教练某时间段是否已有课程需要200ms,加上后只需要5ms。

3. 核心功能实现详解

3.1 排课冲突检测算法

排课最核心的问题就是避免冲突。我实现了双重检查机制:

  1. 教练时间冲突检查
  2. 教室资源冲突检查

关键代码如下:

public boolean checkScheduleConflict(Schedule newSchedule) { // 检查教练是否有时间冲突 int coachConflictCount = scheduleMapper.countCoachConflict( newSchedule.getCoachId(), newSchedule.getStartTime(), newSchedule.getEndTime()); if(coachConflictCount > 0) { throw new BusinessException("该教练在此时间段已有其他课程"); } // 检查教室是否有冲突 if(StringUtils.isNotBlank(newSchedule.getClassroom())) { int roomConflictCount = scheduleMapper.countClassroomConflict( newSchedule.getClassroom(), newSchedule.getStartTime(), newSchedule.getEndTime()); if(roomConflictCount > 0) { throw new BusinessException("该教室在此时间段已被占用"); } } return true; }

对应的MyBatis查询:

<select id="countCoachConflict" resultType="int"> SELECT COUNT(*) FROM schedule WHERE coach_id = #{coachId} AND ( (start_time &lt; #{endTime} AND end_time &gt; #{startTime}) OR (start_time = #{startTime}) ) <if test="excludeId != null"> AND id != #{excludeId} </if> </select>

3.2 批量排课功能

培训机构经常需要为同一课程安排连续多节课。我实现了批量排课功能,可以按周循环排课:

public List<Schedule> createRecurringSchedules(RecurringScheduleRequest request) { List<Schedule> schedules = new ArrayList<>(); LocalDateTime current = request.getFirstClassTime(); for(int i=0; i<request.getWeeks(); i++) { Schedule schedule = new Schedule(); // 设置基本属性... schedules.add(schedule); // 检查冲突 checkScheduleConflict(schedule); // 增加一周 current = current.plusWeeks(1); } scheduleMapper.batchInsert(schedules); return schedules; }

提示:批量操作一定要有事务保护。我在实际使用中发现,如果没有事务,当中间某节课出现冲突时,会导致部分数据已插入而部分没有,造成数据不一致。Spring的@Transactional注解可以很好地解决这个问题。

4. 系统部署与使用指南

4.1 环境准备

  1. JDK 1.8或更高版本
  2. MySQL 5.7+/MariaDB
  3. Maven 3.6+

建议开发环境:

  • IntelliJ IDEA(社区版即可)
  • Lombok插件(必须安装,否则编译会报错)

4.2 快速启动步骤

  1. 克隆源码:

    git clone https://github.com/yourrepo/coach-scheduling-system.git
  2. 创建数据库:

    CREATE DATABASE coach_scheduling DEFAULT CHARACTER SET utf8mb4;
  3. 修改配置: 编辑src/main/resources/application.yml,设置数据库连接信息:

    spring: datasource: url: jdbc:mysql://localhost:3306/coach_scheduling?useSSL=false username: yourusername password: yourpassword
  4. 启动应用:

    mvn spring-boot:run
  5. 访问系统: http://localhost:8080

4.3 常见问题解决

问题1:启动时报"java: You aren't using a compiler supported by lombok..."

  • 解决方案:确保安装了Lombok插件,并在IDE中启用了注解处理

问题2:排课时间显示不正确

  • 检查点:数据库时区设置(建议设置为UTC+8)
    SET GLOBAL time_zone = '+8:00';

问题3:系统运行一段时间后变慢

  • 优化建议:定期清理旧的排课记录,或者为schedule表添加分区

5. 扩展与定制建议

5.1 功能扩展方向

  1. 学员预约功能:在现有基础上增加学员模型,实现课程预约
  2. 微信通知集成:排课变动时自动微信通知教练
  3. 课程评价系统:让学员可以对教练课程进行评分

5.2 性能优化技巧

  1. 缓存热门数据:使用Redis缓存教练列表、热门课程等

    @Cacheable(value = "coaches", key = "'all'") public List<Coach> getAllCoaches() { return coachMapper.selectAll(); }
  2. 分页查询:当排课记录很多时,一定要实现分页

    public PageInfo<Schedule> getSchedules(int pageNum, int pageSize) { PageHelper.startPage(pageNum, pageSize); List<Schedule> list = scheduleMapper.selectAll(); return new PageInfo<>(list); }
  3. 异步日志:使用Log4j2的异步日志减少I/O等待

    <AsyncLogger name="com.yourpackage" level="info"/>

5.3 实际部署建议

  1. 生产环境建议使用Docker部署,便于管理

    FROM openjdk:8-jdk-alpine COPY target/coach-scheduling-0.0.1.jar app.jar ENTRYPOINT ["java","-jar","/app.jar"]
  2. 数据库建议配置定期备份

    # 每天凌晨备份 0 0 * * * /usr/bin/mysqldump -uyouruser -pyourpass coach_scheduling > /backups/coach_$(date +\%Y\%m\%d).sql

这套系统我已经在实际培训场景中使用了一年多,期间根据实际需求进行了多次迭代。最大的体会是:排课系统的核心不在于功能有多复杂,而在于对业务场景的理解深度。比如,最初版本没有考虑教练的休息时间,导致系统允许排通宵课程,后来增加了教练可用时间段配置才解决这个问题。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询