news 2026/10/10 21:33:17

基于SSM的校园学生体温管理系统开发全解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于SSM的校园学生体温管理系统开发全解析

我在帮学校做学生体温管理系统的时候,刚接手并没有直接想着用什么技术框架,而是需求确实摆在面前:每天上午、下午两轮体温填报,班主任要查看全班数据,校医要盯着异常记录,教务处要统计发热人数。用Excel收上来的表经常七零八落,名字和体温对不上号,补填、漏填也没有人管。后来我决定用Spring、SpringMVC、MyBatis这套SSM组合搭一个标准化的校园学生体温管理系统,一套程序跑下来,从学生登录到管理员导出数据,整个链路才算是通了。这篇文章就把这套系统的开发思路、数据库设计、核心配置、部署调试经验完整写出来,给正在做课设、毕设,或者第一次完整接触SSM项目的人一个能直接参考的样板。

这套系统适合谁看?如果你在学校做信息管理类Web开发,或者想在课设里找一个“功能不复杂但足够完整”的SSM项目,那这篇内容就是给你准备的。我尽可能把每一步的“为什么”也讲清楚,而不是单纯贴代码,这样哪怕你用的是别的数据库、别的IDE,也能举一反三。

1. 项目整体设计与需求拆解

1.1 需求不是做个登记表,而是完成一个管理闭环

很多人做这类系统时容易犯一个错误:把“体温管理”理解成一张表单加一个列表,学生填完、老师能看,就觉得完事了。真正到了校园场景里,这套系统的核心需求是一个闭环:学生填报 -> 班主任审核/标记 -> 校医处理异常 -> 管理员统计汇总。

我梳理出的角色和用例大致是这样的:

  • 学生:登录系统,当天在规定时间段内填报体温,填写健康状况(正常/咳嗽/乏力等),查看自己的历史记录。
  • 班主任:查看本班学生的填报情况,提醒未填的学生补填,对体温异常的学生进行确认和标记。
  • 管理员/校医:查看全部班级的填报进度,查看异常记录的处理状态,按班级、按日期统计发热人数和平均体温,并导出日报表。

在后端设计上还要处理几个隐藏需求:防止学生重复提交同一天同一时段的记录;体温数据必须可追溯,谁在什么时间填报的;权限必须隔离,学生不能查看别人的数据,班主任只能看本班数据。这些看似不起眼的需求,直接决定数据库表和Service层方法怎么设计,一定要在一开始就放进需求清单里。

1.2 为什么选SSM而不是Spring Boot

现在很多新项目直接上Spring Boot,但SSM这套组合在Java Web领域依然是“教科书级”的存在。我选SSM的核心原因有三个:

第一,很多学校的课程设计和毕业设计题目会指定使用SSM,因为它的分层结构非常清晰:Controller控制请求,Service处理业务,Mapper负责数据库操作,能让评委和老师一眼看出你有没有掌握Java Web的基础知识。第二,SSM把配置显式地摆在你面前,不像Spring Boot自动配置那么多“魔法”,反而更适合理解Spring IoC、AOP、MVC这些核心原理。第三,MyBatis在处理统计类SQL时非常灵活,像“按日期分组统计发热人数”“查询未填报学生列表”这类需求,用XML里写原生SQL比JPA顺手很多。

这套系统的技术栈具体如下:

组件选型说明
后端框架Spring 5.x + SpringMVC负责IoC管理、事务控制、请求分发
持久层框架MyBatis 3.5.xXML中编写SQL,灵活完成统计查询
数据库MySQL 5.7 / 8.0存储用户、班级、体温记录等数据
连接池Druid 1.2.x提供数据库连接池和监控能力
前端JSP + JSTL + Bootstrap服务端渲染界面,简单稳定
构建工具Maven 3.6+管理依赖、打包部署
运行环境Tomcat 8.5Java Web应用容器

这套组合出来的系统虽然不“新潮”,但稳定、可控,特别适合要写论文的场景——你对每一层做了什么都能说得很清楚。

2. 数据库设计:体温数据怎么存才不别扭

2.1 五张核心表的结构和设计思路

我最终设计的库名叫body_temp_system,一共五张核心表。这里先给出最重要的三张表,剩下的在2.2里说明。

t_user表,存所有账号信息:

CREATE TABLE `t_user` ( `id` INT NOT NULL AUTO_INCREMENT, `username` VARCHAR(50) NOT NULL, `password` VARCHAR(100) NOT NULL, `role` TINYINT NOT NULL DEFAULT 0 COMMENT '0学生 1班主任 2管理员', `real_name` VARCHAR(50) NOT NULL, `class_id` INT DEFAULT NULL, `status` TINYINT NOT NULL DEFAULT 1 COMMENT '1正常 0禁用', PRIMARY KEY (`id`), UNIQUE KEY `uk_username` (`username`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

t_class表,存班级信息:

CREATE TABLE `t_class` ( `class_id` INT NOT NULL AUTO_INCREMENT, `class_name` VARCHAR(100) NOT NULL, `grade` VARCHAR(20) DEFAULT NULL, PRIMARY KEY (`class_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

t_health_record表,存体温填报记录,这是整个系统最核心的表:

CREATE TABLE `t_health_record` ( `id` INT NOT NULL AUTO_INCREMENT, `user_id` INT NOT NULL COMMENT '学生ID', `report_date` DATE NOT NULL COMMENT '填报日期', `period` TINYINT NOT NULL COMMENT '1上午 2下午', `temperature` DECIMAL(4,1) NOT NULL COMMENT '体温', `health_status` TINYINT NOT NULL DEFAULT 0 COMMENT '0正常 1异常', `symptom` VARCHAR(255) DEFAULT NULL COMMENT '咳嗽/乏力等症状描述', `remark` VARCHAR(255) DEFAULT NULL, `report_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uk_user_date_period` (`user_id`, `report_date`, `period`), KEY `idx_report_date` (`report_date`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

为什么单独把user_id、report_date、period三个字段建一个唯一索引?因为业务上同一个人同一天同一个上报时段只能有一条记录。这个唯一索引是在数据库层面防止重复提交的最后一道防线,比在Java代码里先查后插要可靠得多。

2.2 关键字段的细节:精度、时区、外键

设计体温字段时,我用的是DECIMAL(4,1),而不是FLOAT或者DOUBLE。原因很简单:体温只需要精确到小数点后一位,36.5、37.3这种数据,用浮点数存储容易产生精度误差,比如37.30可能变成37.2999999,虽然界面显示没什么问题,但做数值比较时很麻烦。用定点数直接从存储层面规避。

report_time字段我使用了DATETIME类型,并让数据库自动写入当前时间。这里有一个大坑:如果使用MySQL 8.0以上版本,JDBC连接串必须显式指定时区,否则会报The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized。我在jdbc.properties里是这样写的:

jdbc.url=jdbc:mysql://localhost:3306/body_temp_system?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true

allowPublicKeyRetrieval=true是MySQL 8.0配合SSL关闭时常用的一个参数,不然本地连接也可能报Public Key Retrieval is not allowed。

关于外键,很多初学者喜欢在表上直接加FOREIGN KEY约束。但在我这个系统里,我使用的是逻辑外键,没有在数据库层面建立物理外键。原因有两方面:一是学生、班级数据在批量导入时会因为外键约束导致插入顺序必须严格一致;二是系统的查询全是单表加简单关联,MyBatis手动管理关联关系已经足够,出现脏数据反而是业务层的校验没做好。所以我的建议是:课程设计阶段可以用逻辑外键,并在论文中说明为什么不做物理外键,这也是一个亮点评分点。

2.3 关键统计SQL:从“查记录”到“看趋势”

体温管理系统和普通增删改查系统的最大区别在于统计查询。我实际用到最多的三条SQL,分享出来可以帮你少走弯路。

查询当天未填报的学生列表。如果直接用WHERE report_date = today会查不到“没记录的人”,所以要用LEFT JOIN,让学生表作为主表:

SELECT u.id, u.real_name, c.class_name FROM t_user u LEFT JOIN t_class c ON u.class_id = c.class_id LEFT JOIN t_health_record r ON r.user_id = u.id AND r.report_date = #{today} AND r.period = #{period} LEFT JOIN t_health_record r2 ON 1=0 -- 占位,实际可省略 WHERE u.role = 0 AND r.id IS NULL;

实际上第三个LEFT JOIN是不需要的,核心还是让关联条件带上日期和时段,这样r.id IS NULL就表示当天该时段没有任何记录。

统计某天各班级发热人数(假设37.3℃以上算发热):

SELECT c.class_name, COUNT(DISTINCT r.user_id) AS fever_count FROM t_health_record r JOIN t_user u ON r.user_id = u.id JOIN t_class c ON u.class_id = c.class_id WHERE r.report_date = #{date} AND r.temperature >= 37.3 GROUP BY c.class_name ORDER BY fever_count DESC;

这里用COUNT(DISTINCT r.user_id)非常关键。虽然唯一索引已经控制了同一个人同一天同一时段不会重复填报,但在跨时段统计时(比如一天内发热人数),一个人上午发热下午正常,如果不加DISTINCT就会被统计两次。

查询一周内每天的平均体温,用来画趋势图:

SELECT report_date, ROUND(AVG(temperature), 2) AS avg_temp, COUNT(*) AS total_count FROM t_health_record WHERE report_date BETWEEN #{startDate} AND #{endDate} GROUP BY report_date ORDER BY report_date;

这类SQL之所以适合写在MyBatis的Mapper XML里,是因为你可以随时根据前端图表需求调整查询条件,而不需要改Java代码。

3. 开发环境与SSM整合实操

3.1 开发工具清单和版本搭配

很多人在环境搭建上就卡住了,最典型的问题是JDK、Maven、Tomcat版本不一致。我这次使用的组合是:JDK 1.8 + Maven 3.6.3 + MySQL 5.7 + Tomcat 8.5 + IDEA。如果你用IDEA,建议用2020以上的版本,自带Maven绑定和Tomcat集成,能省不少事。

在pom.xml中,Maven依赖这一块建议固定版本,别图省事用最新的大版本。特别是Spring、MyBatis和数据库驱动之间经常出现版本不兼容。我使用的基础依赖如下:

<properties> <spring.version>5.3.18</spring.version> </properties> <dependencies> <!-- Spring核心 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <!-- MyBatis及与Spring整合的桥接包 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.9</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>2.0.6</version> </dependency> <!-- MySQL驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.49</version> </dependency> <!-- Druid连接池 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.8</version> </dependency> <!-- 其他 --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.12.4</version> </dependency> </dependencies>

这里有个细节:如果你用的MySQL是8.0以上驱动版本,那么mysql-connector-java的版本号要改成8.0.28以上,同时驱动类要从com.mysql.jdbc.Driver改成com.mysql.cj.jdbc.Driver。别小看这个变化,90%的“数据库连接失败”都出在这里。

3.2 配置文件逐段跑通

SSM最让人头疼的地方是三个配置文件之间的关系。我把它拆解成一句话:web.xml负责调度,spring容器负责管理业务组件,springmvc容器负责管理Controller。两者通过父子容器相互关联。

web.xml的核心配置:

<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <filter> <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>

特别提醒:DispatcherServlet的url-pattern一定不要写成/*。写成/*会把JSP文件请求也交给SpringMVC处理,导致返回的是Controller字符串而不是渲染后的页面,出现典型的404错误。用/则可以同时处理/login这样的路径请求和静态资源映射。

在spring.xml里,核心是数据源、SqlSessionFactory、Mapper扫描和事务:

<context:component-scan base-package="com.system.service" /> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <property name="driverClassName" value="${jdbc.driver}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </bean> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="configLocation" value="classpath:mybatis-config.xml" /> <property name="mapperLocations" value="classpath:mapper/*.xml" /> </bean> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.system.mapper" /> </bean> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <tx:advice id="txAdvice" transaction-manager="txManager"> <tx:attributes> <tx:method name="add*" propagation="REQUIRED" rollback-for="Exception" /> <tx:method name="update*" propagation="REQUIRED" rollback-for="Exception" /> <tx:method name="delete*" propagation="REQUIRED" rollback-for="Exception" /> <tx:method name="get*" read-only="true" /> </tx:attributes> </tx:advice> <aop:config> <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.system.service..*.*(..))" /> </aop:config>

注意,tx:advice这个配置在Spring 5里面依然可用,但需要引入spring-aop和aspectjweaver依赖。很多项目报“找不到tx命名空间”,就是因为pom里漏了spring-aop。

在springmvc.xml里,最重要的是两个:开启注解驱动、配置视图解析器和静态资源放行。因为页面使用了JSP和静态JS、CSS,必须告诉SpringMVC不要拦截/static/**:

<context:component-scan base-package="com.system.controller" /> <mvc:annotation-driven /> <mvc:resources mapping="/static/**" location="/static/" /> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/" /> <property name="suffix" value=".jsp" /> </bean>

3.3 常用SSM注解与核心业务代码

整个开发过程中,你会反复用到这些SSM常用注解,我先把要掌握的先列出来:

  • @Controller:声明控制器,交给SpringMVC容器管理。
  • @RequestMapping:映射URL,可以用在类和方法上。
  • @ResponseBody:将方法返回值直接写入响应体,常用于返回JSON。
  • @RequestParam:从请求参数中取值,比如@RequestParam("period") Integer period。
  • @PathVariable:从URL路径中取值,比如/record/delete/{id}。
  • @Autowired:按类型自动注入依赖,可以用于Service、Mapper等。
  • @Service:声明业务层组件。
  • @Repository:声明数据访问组件,让Spring容器管理Mapper实现。
  • @Transactional:声明事务,一般加在Service方法上。

以体温上报的核心逻辑为例,这是最典型的“先检查、再插入、事务包裹”的场景。我写了一个简化的Controller和Service示例:

@Controller @RequestMapping("/record") public class HealthRecordController { @Autowired private HealthRecordService recordService; @PostMapping("/submit") @ResponseBody public Result submit(@RequestParam("temperature") Double temperature, @RequestParam("period") Integer period, @RequestParam(value = "symptom", required = false) String symptom, HttpSession session) { User user = (User) session.getAttribute("loginUser"); if (user == null) { return Result.error("登录已过期,请重新登录"); } if (temperature < 35.0 || temperature > 42.0) { return Result.error("体温超出合理范围,请重新测量"); } try { recordService.submitRecord(user.getId(), temperature, period, symptom); return Result.success("上报成功"); } catch (DuplicateSubmitException e) { return Result.error("今天该时段已经上报过了,不要重复提交"); } } }

Service层中,@Transactional保证了插入操作中所有的SQL要么全成功,要么全失败。如果一张“每日填报统计表”在插入记录时同时要修改t_user_status,这一步不要拆开执行,最好是放进同一个方法:

@Service public class HealthRecordServiceImpl implements HealthRecordService { @Autowired private HealthRecordMapper recordMapper; @Transactional(rollbackFor = Exception.class) @Override public void submitRecord(Integer userId, Double temperature, Integer period, String symptom) { // 先查重复,再插入 int count = recordMapper.countByUserAndPeriod(userId, new Date(), period); if (count > 0) { throw new DuplicateSubmitException("重复提交"); } HealthRecord record = new HealthRecord(); record.setUserId(userId); record.setReportDate(new Date()); record.setPeriod(period); record.setTemperature(temperature); record.setSymptom(symptom); record.setHealthStatus(temperature >= 37.3 ? 1 : 0); recordMapper.insert(record); } }

4. 调试部署中的坑与排查实录

4.1 开发阶段最容易踩的5个坑

我在开发这个系统的过程中,几乎把SSM新手可能踩的坑都踩了一遍。这里挑五个最有代表性的,配上实际情况和解决办法。

第一个坑:时区报错。只要你的MySQL是8.0,且JDBC连接串里没加serverTimezone=Asia/Shanghai,启动时几乎必然报时区错误。解决方案上面已经写了,不再重复。补充一点:如果你用IDEA自带的数据库工具测试连接,同样要配置时区分项,否则显示乱码且无法连接。

第二个坑:404,但检查Controller和JSP路径都没问题。这时候优先排查web.xml里的<url-pattern>是不是被写成了/*。另外,还要确认springmvc.xml里的<context:component-scan>是不是只扫描了Controller包,如果把Service、Mapper也放进来扫描,会出现“Bean重复定义”的提示。

第三个坑:Mapper接口和XML文件“对不上号”。比如调用selectByUserId时提示Invalid bound statement (not found)。原因基本就是mapperLocations没有扫描到对应的XML文件,或者XML里的namespace没有写成Mapper接口的全限定名。我的习惯是:Mapper XML文件的目录结构保持和接口包路径一致,例如接口在com.system.mapper,XML文件就放在resources/mapper下,但namespace写成com.system.mapper.HealthRecordMapper。

第四个坑:中文乱码。这个问题的来源有三个层次:数据库连接编码、Servlet过滤器编码、页面编码。数据库连接已经通过characterEncoding=utf8解决;请求编码通过CharacterEncodingFilter解决;页面编码要在JSP顶部写<%@ page contentType="text/html;charset=UTF-8" language="java" %>,三者缺一不可。此外Tomcat的server.xml里最好给Connector加上URIEncoding="UTF-8",否则表单提交的中文参数仍可能乱码。

第五个坑:Druid连接池监控页面和生产连接冲突。如果开启了Druid的Web监控,要注意StatViewServlet的URL映射不能和项目里已有路由冲突。我建议把监控页地址设置为/druid/*,并且在web.xml单独声明:

<servlet> <servlet-name>DruidStatView</servlet-name> <servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class> <init-param> <param-name>resetEnable</param-name> <param-value>false</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>DruidStatView</servlet-name> <url-pattern>/druid/*</url-pattern> </servlet-mapping>

4.2 常见问题速查表

现象可能原因排查/解决建议
启动Tomcat时连接数据库超时数据库服务未启动 / 连接串主机端口错误先确认mysql服务是否启动,再检查jdbc.url
页面能打开但所有CSS没样式静态资源被DispatcherServlet拦截配置<mvc:resources>或在web.xml放行静态资源
表单提交后报400参数类型不匹配,比如体温空值绑定DoubleController参数加required=false或前端校验
登录成功后刷新就回到登录页Session失效 / Cookie路径问题检查登录拦截器是否放行了登录和静态资源请求
数据库连接数飙升Druid连接未正常释放检查事务切面是否生效,Service方法是否被代理
导出报表内容为空统计SQL关联条件错误用SQL客户端先执行同一条SQL,确认有数据再排查前端

4.3 从源码到运行环境的完整部署流程

开发调试和最终部署是两件事。我第一次部署时走了弯路,这里直接给出一个稳定流程。

第一步,用Maven打war包。在IDEA右侧Maven面板里执行clean,然后再执行package。在pom.xml中记得把打包方式改成<packaging>war</packaging>。

第二步,确认war包生成位置。默认在项目的target目录下,文件名一般是项目名-1.0-SNAPSHOT.war。建议把它重命名成简短的英文名,比如bodytemp.war,这样访问路径更好记。

第三步,部署到Tomcat。把bodytemp.war复制到Tomcat安装目录的webapps下,启动Tomcat后会自动解压成bodytemp文件夹。访问地址就是http://localhost:8080/bodytemp/。

第四步,如果部署到云服务器或者VM虚拟机上,还要检查防火墙是否开放了8080端口。Linux下可以使用firewall-cmd --zone=public --add-port=8080/tcp --permanent并重载防火墙。同时数据库要开放远程访问权限,并且给MySQL用户授权的Host要填%而不是localhost。

部署完成后,建议按这个顺序做冒烟测试:先访问登录页并登录管理员账号,确认后台可以正常进入;然后批量创建几个测试学生账号,登录学生端提交一条体温记录;再去班级列表确认记录是否同步;最后到统计页面看对应日期和班级的数据是否出现。只要这个链路通了,系统上线基本就没问题。

4.4 几个提高排查效率的习惯

这里再补充几个在开发调试中帮了我大忙的小习惯。

第一,把MyBatis的SQL日志打开。最简单的方式是在mybatis-config.xml里加:

<settings> <setting name="logImpl" value="STDOUT_LOGGING"/> </settings>

这样每次执行SQL都会在控制台打印预编译语句和参数,你看一眼就知道SQL和参数是不是按预期传的。比在代码里打日志都方便。

第二,多用Postman测试JSON接口。系统里凡是使用@ResponseBody的接口,都可以先通过Postman带参数调用,看返回的JSON是否正确。这能帮你把“后端问题”和“前端问题”快速分离,不需要每次都在浏览器里反复调试。

第三,尽早用Druid监控页面看慢SQL。当页面统计报表加载很慢时,往往不是Java代码的问题,而是SQL没有走索引。打开/druid/sql.html,看执行次数、耗时排行,就能定位到具体SQL,再回头优化索引或者改写关联条件。

我个人在实际操作中的体会是,这个SSM校园学生体温管理系统本身并不复杂,但把数据库约束、事务边界、权限控制和部署流程全部理顺,是需要花不少功夫的。我从最初只会照着教程写几个Mapper接口,到后来能在脑子里完整画出数据流向,靠的就是一遍遍调试这些报错。

最后再分享一个小技巧。这类小型管理系统,表结构设计时我一度想让t_health_record只存体温和状态,把异常处理单独拆到另一张表。后来发现查询时要把学生表、班级表、记录表、处理表来回关联,尤其是导出日报的时候,SQL又长又容易出错。最终我把上报记录、异常标记、处理结果都收敛到“记录表加一张轻量扩展表”的方式,统计SQL短了很多,事务边界也更清晰。如果你接下来想扩展一套微信小程序报送端,这个SSM后台完全可以继续复用,改改接口视图层就能通,这大概就是这套经典组合最让人省心的地方。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/10 21:29:15

基于Java+SSM+Flask的旅社客房收费管理系统详解

市面上这类系统的叫法五花八门&#xff0c;旅社客房收费管理系统、旅店管理系统、客栈管理软件、宾馆客房收费系统、酒店房间收费解决方案&#xff0c;说到底都是同一件事&#xff1a;把房态和账目管明白。最近我完整带了一套基于JavaSSMFlask的旅社客房收费管理系统&#xff0…

作者头像 李华
网站建设 2026/10/10 21:28:17

YOLO卫星遥感舰船检测全流程:标签转换、数据划分与训练部署实战

简介&#xff1a;一套面向卫星遥感舰船检测任务的目标检测数据集&#xff0c;适合遥感图像分析、深度学习目标检测方向的学生、算法工程师以及需要快速获得训练数据的开发者。数据集包含5000张真实场景高质量图片&#xff0c;覆盖港口、近岸、开阔水域等多种环境&#xff1b;标…

作者头像 李华
网站建设 2026/10/10 21:27:49

Matlab实现核岭回归(KRR)多变量预测完整指南:原理、代码与调参

1. 对KRR多变量预测这件事的整体拆解先说说这类“多输入单输出”预测到底在解决什么问题。你手里有一堆特征&#xff0c;比如温度、压力、湿度、转速&#xff0c;要预测一个结果值&#xff0c;比如材料强度、能耗、产量、房价。特征和结果之间往往不是简单的线性关系&#xff0…

作者头像 李华
网站建设 2026/10/10 21:27:12

控制保障与机器学习任务规划:三层架构、训练调参与上线验证

简介&#xff1a;这是一份西安电子科技大学硕士学位论文PDF&#xff0c;主题围绕控制保障系统中的任务规划软件设计与实现&#xff0c;适合从事软件架构、自动化调度、人工智能与机器学习应用开发的工程师及相关专业学生深入学习。论文以某试验验证系统为背景&#xff0c;针对复…

作者头像 李华