实验11-12 基于SpringMVC+Hibernate框架的学生选课分页显示页面的设计
实验11-12 基于SpringMVC+Hibernate框架的学生选课分页显示页面的设计
实验目的
熟练掌握数据库分页技术在 JSP 页面中的实际开发,学会使用 SpringMVC+Hibernate 分层架构完成分页查询,理解物理分页实现思路,掌握通用分页工具类封装、ORM 持久层查询、前端分页交互整套流程。
实验需求与设计思路
功能需求
-
创建 MySQL 学生选课表
字段包含:学号、课程号、课程名、学时数、任课教师、授课地点、学年、学期,插入至少 30 条测试数据 -
采用 SpringMVC+Hibernate 三层架构开发选课查询页面
-
分页规则
每页固定展示 6 条选课数据 -
前端 JSP 页面展示表格
提供分页跳转按钮,UI 简洁美观 -
实现数据库物理分页,减少内存加载压力
整体分层设计
-
Model 层
StudentCourse实体类、通用分页工具PageBean -
Dao 持久层
BaseDao基础父类、StudentCourseDao实现分页查询 -
Service 业务层
封装分页业务逻辑,添加事务控制 -
Controller 控制层
接收前端页码参数,传递分页数据到视图 -
View 视图层
JSP 页面循环渲染选课列表、分页按钮
实验成果
代码分析
PageBean.java(util 包)
点击查看代码
package util;
import java.util.List;
public class PageBean<T> {
private Integer currentPage;
private final Integer pageSize = 6;
private Integer totalCount;
private List<T> list;
// 自动计算总页数
public Integer getTotalPage() {
if(totalCount == null || totalCount <=0) return 0;
return totalCount % pageSize == 0 ? totalCount/pageSize : totalCount/pageSize +1;
}
// getter setter
public Integer getCurrentPage() {return currentPage;}
public void setCurrentPage(Integer currentPage) {this.currentPage = currentPage;}
public Integer getPageSize() {return pageSize;}
public Integer getTotalCount() {return totalCount;}
public void setTotalCount(Integer totalCount) {this.totalCount = totalCount;}
public List<T> getList() {return list;}
public void setList(List<T> list) {this.list = list;}
}
StudentCourse.java(entity 包)
点击查看代码
package entity;
public class StudentCourse {
private Integer id;
private String stuNo; //学号
private String courseNo; //课程号
private String courseName; //课程名
private Integer classHour; //学时
private String teacherName; //教师
private String classRoom; //教室
private String schoolYear; //学年
private Integer term; //学期
public StudentCourse(){}
// getter setter
public Integer getId() {return id;}
public void setId(Integer id) {this.id = id;}
public String getStuNo() {return stuNo;}
public void setStuNo(String stuNo) {this.stuNo = stuNo;}
public String getCourseNo() {return courseNo;}
public void setCourseNo(String courseNo) {this.courseNo = courseNo;}
public String getCourseName() {return courseName;}
public void setCourseName(String courseName) {this.courseName = courseName;}
public Integer getClassHour() {return classHour;}
public void setClassHour(Integer classHour) {this.classHour = classHour;}
public String getTeacherName() {return teacherName;}
public void setTeacherName(String teacherName) {this.teacherName = teacherName;}
public String getClassRoom() {return classRoom;}
public void setClassRoom(String classRoom) {this.classRoom = classRoom;}
public String getSchoolYear() {return schoolYear;}
public void setSchoolYear(String schoolYear) {this.schoolYear = schoolYear;}
public Integer getTerm() {return term;}
public void setTerm(Integer term) {this.term = term;}
}
BaseDao.java(dao 包)
点击查看代码
package dao;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
public class BaseDao {
@Autowired
private SessionFactory sessionFactory;
public Session getSession(){
return sessionFactory.getCurrentSession();
}
}
StudentCourseDao.java
点击查看代码
package dao;
import entity.StudentCourse;
import org.hibernate.Query;
import org.hibernate.Transaction;
import org.springframework.stereotype.Repository;
import util.PageBean;
import java.util.List;
@Repository
public class StudentCourseDao extends BaseDao {
public PageBean<StudentCourse> pageQuery(Integer currentPage){
PageBean<StudentCourse> page = new PageBean<>();
page.setCurrentPage(currentPage);
int size = page.getPageSize();
org.hibernate.Session session = getSession();
Transaction tx = session.beginTransaction();
// 查询总记录数
Query countQ = session.createQuery("select count(*) from StudentCourse");
Long total = (Long) countQ.uniqueResult();
page.setTotalCount(total.intValue());
// 分页截取数据
Query dataQ = session.createQuery("from StudentCourse");
dataQ.setFirstResult((currentPage-1)*size);
dataQ.setMaxResults(size);
List<StudentCourse> list = dataQ.list();
page.setList(list);
tx.commit();
return page;
}
}
StudentCourseService.java
点击查看代码
package service;
import dao.StudentCourseDao;
import entity.StudentCourse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import util.PageBean;
@Service
public class StudentCourseService {
@Autowired
private StudentCourseDao dao;
@Transactional(readOnly = true)
public PageBean<StudentCourse> getPage(Integer pageNum){
// 页码为空或小于1,默认第一页
if(pageNum == null || pageNum <1) pageNum = 1;
return dao.pageQuery(pageNum);
}
}
CourseController.java
点击查看代码
package controller;
import entity.StudentCourse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import service.StudentCourseService;
import util.PageBean;
@Controller
@RequestMapping("/course")
public class CourseController {
@Autowired
private StudentCourseService service;
@RequestMapping("/list")
public String list(@RequestParam(value="page",required = false) Integer page, Model model){
PageBean<StudentCourse> pageData = service.getPage(page);
model.addAttribute("pageData",pageData);
return "courseList";
}
}
courseList.jsp 前端分页页面
点击查看代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>学生选课分页查询系统</title>
<style>
table{width:90%;margin:20px auto;border-collapse: collapse;}
th,td{border:1px solid #999;padding:8px;text-align:center}
th{background:#007bff;color:white}
.page-box{text-align:center;margin:20px}
a{margin:0 5px;text-decoration:none}
</style>
</head>
<body>
<h2 style="text-align:center">学生选课信息分页展示</h2>
<table>
<tr>
<th>学号</th>
<th>课程号</th>
<th>课程名称</th>
<th>学时</th>
<th>授课教师</th>
<th>上课地点</th>
<th>学年</th>
<th>学期</th>
</tr>
<!-- 遍历分页数据 -->
<c:forEach items="${pageData.list}" var="sc">
<tr>
<td>${sc.stuNo}</td>
<td>${sc.courseNo}</td>
<td>${sc.courseName}</td>
<td>${sc.classHour}</td>
<td>${sc.teacherName}</td>
<td>${sc.classRoom}</td>
<td>${sc.schoolYear}</td>
<td>${sc.term==1?'第一学期':'第二学期'}</td>
</tr>
</c:forEach>
</table>
<div class="page-box">
总记录:${pageData.totalCount}条,共${pageData.totalPage}页
<br>
<!-- 上一页 -->
<c:if test="${pageData.currentPage > 1}">
<a href="/course/list?page=${pageData.currentPage-1}">上一页</a>
</c:if>
当前第${pageData.currentPage}页
<!-- 下一页 -->
<c:if test="${pageData.currentPage < pageData.totalPage}">
<a href="/course/list?page=${pageData.currentPage+1}">下一页</a>
</c:if>
</div>
</body>
</html>
结果介绍


网站访问链接:http://47.111.183.105:8080/CourseSelect/index.jsp
问题解决
问题一:首次访问无 page 参数,页码为 0 分页错乱
解决:Service 层增加判断,page 为空或小于 1 强制赋值为 1,保证分页偏移量计算正确。
问题二:总页数计算出现余数丢失
解决:修改 PageBean 的getTotalPage(),使用三元运算符判断取模结果,有余数则页数 + 1。
问题三:页面布局简陋,UI 不美观
解决:添加 CSS 样式美化表格、分页区域,调整文字居中、配色,提升页面观感。
实验总结
这次实验完整做完了 MVC 分层搭配 Hibernate 的选课分页功能,从头到尾完整走了一遍开发流程:从建数据库表、写分层后端代码、封装分页计算工具,再到 JSP 页面渲染展示全部实操完成。
通过动手敲代码,我们真正分清了三层架构每一层的职责,也体会到 Hibernate 这种 ORM 框架不用手写大量 SQL,大大简化数据库操作,彻底吃透分页功能底层实现原理。
写代码过程中踩了不少分页边界、事务、参数接收的坑,一步步排查修复,也锻炼了自己调试代码、定位 bug 的能力,同时意识到分层封装、页码边界判断、数据库事务管理在 Web 项目里缺一不可。

浙公网安备 33010602011771号