英山县城乡建设规划局网站,wordpress体验,优秀网页设计案例赏析之淘宝,wordpress邮箱修改背景#xff1a;13张表是怎么把人逼疯的#xff1f; 做毕设时#xff0c;导师一句“比赛日程系统#xff0c;功能要全”#xff0c;听起来简单#xff0c;一拆表就傻眼#xff1a; 赛事、项目、队伍、队员、裁判、场地、日程、积分、公告、报名、轮空、消息、日志——1…背景13张表是怎么把人逼疯的做毕设时导师一句“比赛日程系统功能要全”听起来简单一拆表就傻眼赛事、项目、队伍、队员、裁判、场地、日程、积分、公告、报名、轮空、消息、日志——13张表瞬间到位。大多数同学第一反应是“堆字段”外键到处拉结果循环引用A 表删不掉B 表查不动C 表一更新D 表全锁行N1 查询赛程列表接口for 循环里顺手getTeam().getPlayers()生产环境 200 ms 能飙到 5 s事务边界模糊一个“生成日程”按钮里层调了 4 个 Service外层没加Transactional回滚只回一半数据直接乱套毕设答辩前夜一边改 SQL 一边哭的场景懂的都懂。技术选型MyBatis 还是 JPA多表关联场景两条路线都能走但踩坑姿势不同维度MyBatisSpring Data JPASQL 可控手写 XML复杂 Join 一目了然靠Query或方法名调试要开 SQL 日志缓存/懒加载无默认自己写一级缓存懒加载一不小心 N1分页手写 count 查询Pageable一行代码搞定代码量每个表 4 个文件XMLMapper注解实体Repository 接口即可学习曲线低但后期 SQL 爆炸前期爽后期要懂实体状态、flush、detach结论毕设周期短、表关联深、导师要求“规范”JPA 更香若后续要极端优化可再局部写 SQL两者混用 Spring 也支持。核心模型13 张表的关系长这样先放 ER 简图混个眼熟关键关系一句话总结赛事 1-N 项目项目 1-N 日程日程 N-N 队伍中间表 schedule_team日程 1-1 场地队伍 N-N 队员中间表 team_player……下面用 JPA 注解落地只贴核心片段能跑即可。1. 赛事实体Entity Table(name t_event) public class Event { Id GeneratedValue private Long id; private String name; private LocalDate startDate; private LocalDate endDate; OneToMany(mappedBy event, cascade CascadeType.ALL, orphanRemoval true) private ListItem items new ArrayList(); }2. 项目实体Entity Table(name t_item) public class Item { Id GeneratedValue private Long id; private String itemName; // 如“男子篮球” ManyToOne(fetch FetchType.LAZY) JoinColumn(name event_id) private Event event; OneToMany(mappedBy item) private ListSchedule schedules new ArrayList(); }3. 日程实体最复杂Entity Table(name t_schedule) public class Schedule { Id GeneratedValue private Long id; private LocalDateTime startTime; private LocalDateTime endTime; ManyToOne(fetch FetchType.LAZY) JoinColumn(name item_id) private Item item; ManyToOne(fetch FetchType.LAZY) JoinColumn(name venue_id) private Venue venue; ManyToMany JoinTable(name schedule_team, joinColumns JoinColumn(name schedule_id), inverseJoinColumns JoinColumn(name team_id)) private SetTeam teams new HashSet(); }注意全部用LAZY只在 Service 里写JOIN FETCH解决 N1多对多再建中间表避免双向List造成无限递归 JSON实体类绝不暴露toString()含关联字段栈溢出警告DTO 转换不让 Entity 裸奔Controller 直接返回 Entity会把懒加载代理拖进 Jackson秒抛LazyInitializationException暴露内部字段循环引用 500套路MapStruct 一行注解搞定Mapper(componentModel spring) public interface ScheduleMapper { ScheduleDto toDto(Schedule s); ListScheduleDto toDto(ListSchedule list); }DTO 里只留venueName、teamNames等扁平字段前端开心后端安全。事务与性能生成日程的正确姿势需求根据“项目轮次”一键生成 48 条日程涉及 4 张表写操作。下面代码演示“事务批量幂等”三位一体Service RequiredArgsConstructor public class ScheduleGenService { private final ScheduleRepository scheduleRepository; private final VenueRepository venueRepository; private final IdGenerator idGenerator; // 雪花算法保证幂等 Transactional // 1. 事务边界 public ListSchedule generate(Item item, int rounds){ // 2. 幂等先查重 if(scheduleRepository.countByItemId(item.getId()) 0){ throw new BizException(日程已存在禁止重复生成); } ListVenue venues venueRepository.findAllBySport(item.getSport()); ListSchedule batch new ArrayList(rounds * venues.size()); for(int i0; irounds; i){ for(Venue v : venues){ Schedule s new Schedule(); s.setId(idGenerator.nextId()); // 3. 提前设主键批量插入可走 JDBC 批处理 s.setItem(item); s.setVenue(v); s.setStartTime(calcStartTime(i, v)); batch.add(s); } } // 4. 批量保存 scheduleRepository.saveAll(batch); return batch; } }要点事务只加在写服务读接口不加减少锁范围提前分配主键MySQL 批插入rewriteBatchedStatementstrue秒级 1w接口幂等靠业务键itemIdround不是单纯依赖数据库唯一索引安全三板斧SQL 注入JPA 只要用方法名或参数绑定:xxx基本免疫手写Query也杜绝拼接批量更新MySQL 的on duplicate key update配合JpaRepository的Modifying注意分片一次 500 条最稳接口幂等除业务判断外前端点“生成”按钮后置灰UUID 令牌后端用 RedisSETNX做双重校验防重放生产环境避坑清单双向关联绝不写cascade CascadeType.ALL了事级联删除一跑半库数据蒸发枚举字段统一Enumerated(STRING)防止序号移位全崩逻辑删除加deleted字段手写WHERE deleted 0拦截JPA 2 级缓存不会自动过滤记得配Where多对多中间表别加业务字段一旦加字段就升成实体否则后续补字段全表锁生产环境打开spring.jpa.show-sqlfalse用 datasource-proxy 慢查询日志替代别让控制台刷屏把性能吃光可扩展思考赛制说改就改怎么办当前模型只支持“单循环积分制”如果导师突然说“加淘汰赛、加复活赛”硬编码if/else直接爆炸。留给读者的作业把“赛制”抽象成 Strategy 接口提供ScheduleStrategy.generate()项目表加strategy_type字段与 Spring 的Strategy自动装配联动新建模块schedule-strategy-elimination遵循相同 DTO做到“热插拔”先动手把生成日程 Service 拆成“规则引擎执行器”跑通单元测试你就能在答辩时自信回答“系统支持任意赛制”——导师微笑你稳过。把 13 张表拆干净、事务扣稳、接口拍平比赛日程系统就不再是“毕设噩梦”而是简历上能吹的亮点。代码给你了坑也标好了下一步要不要把“淘汰赛”模块真正写出来就看你想不想让自己的毕设从 80 分跳到 95 分。