高校成绩管理数据库系统的设计与实现
设计数据库:张成强负责数据字典,数据流图卢鹏宇负责 E-R 图的编辑,和表的设计黄益秒负责索引分区的设计,和具体实现
实现功能:三人各自完成前端、后端、数据库连接的功能。
需求分析
随着中国高等教育的蓬勃发展,大学生人数逐步上升。同时,高校是教学和科研的重要基地,同时还是培养人才的重要场所。随着计算机技术的发展和互联网时代的到来,学习的教学管理受到了极大的挑战。随着学校的规模不断扩大,学生数量急剧增加,学生的成绩信息也成倍增长。这使得部门工作人员的工作量也急剧增加,出现的错误也会随之增加。因此学校的成绩管理面临新的需求,即在疏通各部门尤其是各系之间信息渠道的基础上,建立全校共享数据库。由授课教师来完成成绩录入,而学生可以自行查询成绩。这样除了减轻教学管理部门人员的工作负担,还可以减少信息错误的发生,同时为其他部门甚至全校教职工提供信息服务。建立现代化办公的工作环境,极大地减轻了管理人员的工作量,提高工作效率,并且实现了部门信息管理与学校自动化办公的有机结合。高校成绩管理系统存在的主要问题就是“信息孤岛”的问题。运行计算机技术与网络技术,可以极大便利学生与教师,管理效率大大提高。运行本系统,需要配置好 MySQL 数据库,安装相应的 Java 环境,并下载对应的数据库连接 jar 包。
数据需求描述
系统的数据主要包括学生、教师等的人员信息,课程、专业、学院等基本信息,最重要的是学生成绩信息。下面以数据流图与数据字典的形式详细描述系统的数据需求。
初级数据流图
图 1.1 学生成绩管理系统初级数据流图
详细数据流图
图 1.2 教师录入成绩数据流图
图 1.3 学生信息查询数据流图
图 1.4 高权限教师数据流图
数据字典
数据结构条目
数据结构名
学生
别 名
学生基本信息
描 述
这是学生成绩管理系统的主要数据结构,定义了一个学生的基本信息
组 成
学号,专业(外键),姓名,性别,年龄,平均绩点,已修学分,联系电话,生源地,登录密码,班级编号(外键)
数据项条目
数据项名
学号
别 名
学生编号
描 述
唯一标识每个学生
定 义
CHAR(20)
取值范围
1-20 个字符
取值含义
顺序编号
位 置
学生表
数据项名
专业
别 名
学生专业
描 述
表示这个学生所属专业
定 义
CHAR(20)
取值范围
1-20 个字符
取值含义
按实际需求
位 置
学生表
数据项名
姓名
别 名
学生名称
描 述
学生生活中的称呼
定 义
CHAR(20)
取值范围
1-20 个字符
取值含义
自定义
位 置
学生表
数据项名
性别
别 名
学生性别
描 述
区分学生的一个指标
定 义
CHAR(1)
取值范围
男或女
取值含义
从{男,女}中选择
位 置
学生表
数据项名
班级
别 名
所属班级
描 述
这个学生的所属班级
定 义
CHAR(20)
取值范围
1 到 20 个字符
取值含义
自定义
位 置
学生表
数据项名
年龄
别 名
出生日期
描 述
一个人什么时候出生的
定 义
INT
取值范围
0-100
取值含义
按照身份证上取值
位 置
学生表
数据项名
平均绩点
别 名
平均成绩
描 述
该学生的平均成绩
定 义
DOUBLE
取值范围
0-5
取值含义
按照成绩取值
位 置
学生表
数据项名
已修学分总数
别 名
学生取得的学分
描 述
一个学生从入学到现在获得的学分
定 义
INT
取值范围
0-300
取值含义
按照课程学分取值
位 置
学生表
数据项名
联系电话
别 名
电话号码
描 述
该学生电话号码
定 义
CHAR(20)
取值范围
1-20 个字符
取值含义
自定义
位 置
学生表
数据项名
生源地
别 名
地区
描 述
一个学生之前就读的地区
定 义
CHAR(20)
取值范围
1-20 个字符
取值含义
自定义
位 置
学生表
数据项名
登录密码
别 名
密码
描 述
该学生登录系统的密码
定 义
CHAR(20)
取值范围
1-20 个字符
取值含义
自定义
位 置
学生表
数据结构条目
数据结构名
课程信息
别 名
课程基本信息
描 述
这是学生成绩管理系统的主要数据结构,定义了一门课程的基本信息
组 成
课程编号,课程名,课程学分,课程学时,开设学期,考核方式,任课教师(外键),开设学院(外键)
数据项条目
数据项名
课程编号
别 名
课程的编码
描 述
一个课程的唯一标识符
定 义
CHAR(20)
取值范围
1-20 个字符
取值含义
顺序取值
位 置
课程信息表
数据项名
课程名
别 名
课程称谓
描 述
一个课程的名称
定 义
CHAR(20)
取值范围
1-20 个字符
取值含义
自定义
位 置
课程信息表
数据项名
课程学分
别 名
学分
描 述
修完该课程获得的学分
定 义
INT
取值范围
0-10
取值含义
按照实际课程需求
位 置
课程信息表
数据项名
课程学时
别 名
学时
描 述
该课程这一学期所需要的上课时间
定 义
INT
取值范围
0-100
取值含义
按照实际课程需求
位 置
课程信息表
数据项名
开设学期
别 名
教学学期
描 述
课程开设的学期
定 义
CHAR(20)
取值范围
1-20 个字符
取值含义
自定义
位 置
课程信息表
数据项名
考核方式
别 名
考试或考查
描 述
该课程的考察方式
定 义
CHAR(2)
取值范围
{考试,考查}
取值含义
按照实际课程需求
位 置
课程信息表
数据结构条目
数据结构名
教师信息
别 名
教师基本信息
描 述
这是学生成绩管理系统的主要数据结构,定义了一门课教师的基本信息
组 成
工号,姓名,性别,职称,联系电话,权限级别,登录密码,年龄,学院编号(外键)
数据项条目
数据项名
工号
别 名
教师编号
描 述
参与教学教师的编号
定 义
CHAR(20)
取值范围
1-20 个字符
取值含义
顺序取值
位 置
教师信息表
数据项名
姓名
别 名
老师姓名
描 述
老师的称呼
定 义
CHAR(20)
取值范围
1-20 个字符
取值含义
身份证上的称谓
位 置
教师信息表
数据项名
性别
别 名
老师性别
描 述
老师的性别
定 义
CHAR(1)
取值范围
{男,女}
取值含义
选择其中一个
位 置
教师信息表
数据项名
职称
别 名
老师职称
描 述
老师的职称
定 义
CHAR(20)
取值范围
1-20 个字符
取值含义
教师的职称
位 置
教师信息表
数据项名
联系电话
别 名
电话号码
描 述
老师的联系方式
定 义
CHAR(20)
取值范围
1-20 个字符
取值含义
实际需求取值
位 置
教师信息表
数据项名
权限级别
别 名
系统权限
描 述
该教师登录系统获得的权限
定 义
INT
取值范围
0–10
取值含义
顺序取值
位 置
教师信息表
数据项名
登录密码
别 名
密码
描 述
教师登录系统的密码
定 义
CHAR(20)
取值范围
1-20 个
取值含义
教师的登录密码
位 置
教师信息表
数据项名
年龄
别 名
出生日期
描 述
教师的年龄
定 义
INT
取值范围
0-100
取值含义
教师年龄大小
位 置
教师信息表
数据结构条目
数据结构名
班级信息
别 名
班级基本信息
描 述
这是学生成绩管理系统的主要数据结构,定义了一个班级的基本信息
组 成
班级编号,班级名
数据项名
班级编号
别 名
班级代号
描 述
该班级的唯一标识符
定 义
CHAR(20)
取值范围
1-20 个字符
取值含义
实际需求取值
位 置
班级信息表
数据项条目
数据项名
班级名
别 名
班级名称
描 述
该班级的称呼
定 义
CHAR(20)
取值范围
1-20 个字符
取值含义
实际需求取值
位 置
班级信息表
数据结构条目
数据结构名
专业信息
别 名
专业基本信息
描 述
这是学生成绩管理系统的主要数据结构,定义了一个专业的基本信息
组 成
专业编号,专业名,所属学院(外键)
数据项条目
数据项名
专业编号
别 名
专业代号
描 述
该专业的唯一表示符
定 义
CHAR(20)
取值范围
1-20 个字符
取值含义
实际需求取值
位 置
专业信息表
数据项名
专业名
别 名
专业称呼
描 述
该专业的称谓
定 义
CHAR(20)
取值范围
1-20 个字符
取值含义
实际需求取值
位 置
专业信息表
数据项名
所属学院
别 名
管辖学院
描 述
该专业在哪个学院下开设
定 义
CHAR(20)
取值范围
1-20 个字符
取值含义
实际需求取值
位 置
专业信息表
数据结构条目
数据结构名
学院信息
别 名
专业基本信息
描 述
这是学生成绩管理系统的主要数据结构,定义了一个学院的基本信息
组 成
学院编号,学院名
数据项条目
数据项名
学院编号
别 名
学院的代号
描 述
该学院的唯一标识符
定 义
CHAR(20)
取值范围
1-20 个字符
取值含义
实际需求取值
位 置
学院信息表
数据项名
学院名
别 名
学院名称
描 述
该学院的称呼
定 义
CHAR(20)
取值范围
1-20 个字符
取值含义
实际需求取值
位 置
学院信息表
数据结构条目
数据结构名
学生成绩
别 名
学生成绩信息
描 述
这是学生成绩管理系统的主要数据结构,定义了一个学生成绩的基本信息
组 成
学号(外键),课程编号(外键),成绩
数据项条目
数据项名
成绩
别 名
绩点
描 述
学生在这门课的成绩
定 义
INT
取值范围
0-100
取值含义
实际需求取值
位 置
学生成绩表
数据结构条目
数据结构名
开设信息
别 名
课程开设信息
描 述
这是学生成绩管理系统的主要数据结构,定义了一个课程开设的基本信息
组 成
课程编号(外键),班级编号(外键)
数据存储条目
数据存储名
学生成绩单
别名
学生成绩清单
描述
学生考试成绩的具体信息
数据流来源
教师
数据流去向
学生成绩数据库
组成
学生名,教师名,课程名,分数
数据处理条目
处理过程名
学生成绩录入
说明
教师将成绩单录入到学生成绩数据库
流入数据流
学生成绩单
流出数据流
课程平均成绩,不及格学生名单
处理逻辑:将学生成绩添加到学校成绩数据库中,更新学生的绩点。;如果成绩几个,则将该学生的已修学分增加相应的学分,平均绩点进行更新。;否则,将该条目添加不及格名单中,并将平时绩点更新。
处理逻辑:将学生成绩添加到学校成绩数据库中,更新学生的绩点。;如果成绩几个,则将该学生的已修学分增加相应的学分,平均绩点进行更新。;否则,将该条目添加不及格名单中,并将平时绩点更新。
根据上面的数据字典,我们创建了如下的 UML 图。
图 1.5 成绩管理系统 UML 图
系统功能需求
- 成绩管理主要是教务处对教师、对课程、对学生成绩管理,以便于教师,学生能够随时对学生成绩进行各种查询。
- 他服务的对象不同,提供的功能也不同。
- 高权限教师(系统管理员)
图 1.6 系统管理员功能模块图
学生信息管理:按学好可以查找到学生的详细信息,并可以添加、删除、修改学生信息
教师信息管理:教师以学院为单位划分,可按学院,按教师名,教师号等方式查看教师信息,并由添加,删除、修改教师信息的功能。
课程管理:可以按课程编号查看课程的详细信息,可以添加,删除修改开课记录。
班级开课管理,以班级为单位,根据班级进行开课管理
成绩管理:按学号可以查找学生的全部成绩信息。可以查看该学生的成绩但没有修改成绩功能。成绩录入应由相应老师完成。
学院信息管理,查看,添加,修改,删除学院信息。
专业信息管理,查看,添加,修改,删除专业信息。
班级信息管理,查看,添加,修改,删除班级信息。
普通教师
教师登录后可以修改自己的教师信息,可以修改登录密码,以班级为单位查询学生的课程信息,以班级为单位录入成绩。可以查看任课情况。
图 1.7 教师功能模块图
成绩录入模块:根据教师编号,上课学期,查询所有开课记录,以及开课记录对应班级的所有学生,对每个学生的该科成绩进行录入修改。
成绩查询模块:教师只能查询自己教授的课程的所有同学的成绩。可获得不及格学生名单。课程的平均成绩。
教师任课情况查询:自动获得教师的所有任课情况, 包括课程名称,班级名称,平均成绩。
学生
学生登陆后可以修改自己的信息,可以修改登陆密码;查看全部已考科目的成绩,查看本学期成绩以及不及格科目成绩,查看本学期或学年的班级以及年级名次,以及班级课表、已修学分、总平均绩点、专业教学计划查询等查询。
图 1.8 学生功能模块图
成绩查询:
学生成绩查询:按学期(学年)查询,获得该学期(学年)成绩单,平均绩点,不及格科目,班级排名,年级排名。
课程平均成绩查询:按班级、学期(学年)查询,获得该学期(学年)各个课程的平均成绩。
课程查询:
班级课程开课查询:根据学期查询,上课科目,任课教师
学生教学计划查询:专业教学计划,已修学分,平均绩点。(毕业最低学分,毕业最低绩点)已修科目各科成绩。
其他性能需求
该系统应支持多用户同时对数据库进行访问,即支持并发。
实现方法主要是通过 Java 数据源进行数据库连接,并且 Servlet 编程自带多线程可以支持并发,以此来提升响应速度。
当然响应时间越短越好,但考虑到服务器成本问题,实际响应时间不需要很段,因为也没有必要,在数据访问高峰期,如期末考后,则应该增强服务器的性能。
因此,数据库服务器性能最好能动态变化。因此需要在统计高峰期后做好高并发准备。
概念结构设计
下图 2-1-1 为教师 ER 图,其属性包括姓名、教师编号、性别、职称、年龄、联系电话、登录密码、权限级别。
图 2-1-1 教师 ER 图
下图 2-1-2 为学生 ER 图,其属性包括姓名、学号、性别、专业编号、平均绩点、已修学分总数、联系电话、登录密码、生源所在地、班级编号、年龄。
图 2-1-2 学生 ER 图
下图 2-1-3 为课程 ER 图,其属性包括课程编号、课程名称、开设学院、课程学分、课程学时、开设学期、考核方式、任课教师。
图 2-1-3 课程 ER 图
下图 2-1-4 为学院 ER 图,其属性包括学院编号、学院名
图 2-1-4 学院 ER 图
下图 2-1-5 为专业 ER 图,其属性包括专业编号、专业名、所属学院编号。
图 2-1-5 专业 ER 图
下图 2-1-6 为班级 ER 图,其属性包括班级编号、班级名、所属学院编号、所属专业编号。
图 2-1-6 班级 ER 图
全局 E-R 图
下图 2-2-1 为局部 ER 图合并成的全局 ER 图,其中课程和班级为 n:m 的联系,联系名为“开设”;课程和学生为 n:m 的联系,联系名为“选修”,“选修”具有成绩属性;班级和学生为 1:n 的联系,联系名为“属于”;专业和学生为 1:n 的联系,联系名为“属于”;学院和专业为 1:n 的联系,联系名为“属于”;学院和教师为 1:n 的联系,联系名为“属于”;课程和教师为 n:m 的联系,联系名为“任教”。
图 2-2-1 全局 ER 图
优化 E-R 图
下图 2-3-1 为优化后的 ER 图,删除了学生、专业、教师实体中冗余的属性,将课程信息的开设学院设为外键。
图 2-3-1 优化后的全局 ER 图
在做课程设计的过程中,考虑到一门课在不同的学期可能是不同的老师教,所以把课程字段中的开设学期和任课老师去掉了。
逻辑结构设计
关系模式设计
加红的是主键,加波浪线的是外键
课程(课程编号,开设学院,课程名称,课程学分,课程学时,考核方式)
班级(班级编号,班级名)
学生(学号,班级编号,专业编号,姓名,性别,年龄,登录密码,联系电话,已修学分总数,平均绩点,生源所在地)
专业(专业编号,学院编号,专业名)
学院(学院编号,学院名)
教师(教师编号,学院编号,姓名,性别,年龄,职称,登录密码,权限级别,联系电话)(7)选修信息(学号,课程编号,任课教师,课程名称,成绩,学期)
开设信息(课程编号,班级编号)
关系模式的优化
检查各个关系模式是否满足 1NF、2NF,消除关系模式中的冗余与传递依赖。
使整个关系模式都满足 BCNF,从而优化关系模式。
加红的是主键,加波浪线的是外键
课程(课程编号,开设学院,课程名称,课程学分,课程学时,考核方式)
班级(班级编号,班级名)
学生(学号,班级编号,专业编号,姓名,性别,年龄,登录密码,联系电话,已修学分总数,平均绩点,生源所在地)
专业(专业编号,学院编号,专业名)
学院(学院编号,学院名)
教师(教师编号,学院编号,姓名,性别,年龄,职称,登录密码,权限级别,联系电话)
选修信息(学号,课程编号,教师编号,成绩,学期)
开设信息(课程编号,班级编号)
数据类型定义
课程表
表 3-2-1 课程表数据类型
数据项
数据类型
长度
完整性约束
备注
课程编号
CHAR
20
主键,唯一,非空
开设学院
CHAR
20
外键
课程名称
CHAR
20
课程学分
DOUBLE
0-10
课程学时
DOUBLE
0-100
考核方式
CHAR
2
班级表
表 3-2-2 班级表数据类型
数据项
数据类型
长度
完整性约束
备注
班级编号
CHAR
20
主键,唯一,非空
班级名
CHAR
20
学生表
表 3-2-3 学生表数据类型
数据项
数据类型
长度
完整性约束
备注
学号
CHAR
20
主键,唯一,非空
班级编号
CHAR
20
外键
专业编号
CHAR
20
外键
姓名
CHAR
20
性别
CHAR
1
年龄
INT
0-100
登录密码
CHAR
20
联系电话
CHAR
20
已修学分总数
DOUBLE
0-300
平均绩点
DOUBLE
0-5
生源所在地
CHAR
20
专业表
表 3-2-4 专业表数据类型
数据项
数据类型
长度
完整性约束
备注
专业编号
CHAR
20
主键,唯一,非空
学院编号
CHAR
20
外键
专业名
CHAR
20
学院表
表 3-2-5 课程表数据类型
数据项
数据类型
长度
完整性约束
备注
学院编号
CHAR
20
主键,唯一,非空
学院名
CHAR
20
教师表
表 3-2-6 课程表数据类型
数据项
数据类型
长度
完整性约束
备注
教师编号
CHAR
20
主键,唯一,非空
学院编号
CHAR
20
外键
姓名
CHAR
20
性别
CHAR
1
年龄
INT
0-100
职称
CHAR
20
登录密码
CHAR
20
权限级别
CHAR
20
联系电话
CHAR
20
选修信息表
表 3-2-7 课程表数据类型
数据项
数据类型
长度
完整性约束
备注
学号
CHAR
20
外键
学号、课程编号和任课教师一起构成主键
课程编号
CHAR
20
外键
学号、课程编号和任课教师一起构成主键
教师编号
CHAR
20
外键
学号、课程编号和任课教师一起构成主键
成绩
DOUBLE
255
学号、课程编号和任课教师一起构成主键
学期
CHAR
20
学号、课程编号和任课教师一起构成主键
开设信息表
表 3-2-8 课程表数据类型
数据项
数据类型
长度
完整性约束
备注
课程编号
CHAR
20
外键
课程编号和班级编号一起构成主键
班级编号
CHAR
20
外键
课程编号和班级编号一起构成主键
物理结构设计
聚簇设计
班级:需要在“班级编号”列上建立聚簇,该列为主键,经常用于连接查询并且装入属性后属性值很少修改 。
课程:需要在“课程编号”列上建立聚簇,该列为主键,经常用于连接查询并且装入属性后属性值很少修改 。
开设信息:需要在“课程编号”和“班级编号”列上建立聚簇,该列为主键,经常用于连接查询并且装入属性后属性值很少修改 。
教师:需要在“教师编号”列上建立聚簇,该列为主键,经常用于连接查询并且装入属性后属性值很少修改 。
学生:需要在“学号”列上建立聚簇,该列为主键,经常用于连接查询并且装入属性后属性值很少修改 。
选修信息:需要在“课程编号”和“学号”和“任课教师”列上建立聚簇,该列为主键,经常用于连接查询并且装入属性后属性值很少修改 。
索引设计
班级:对属性“班级编号”建立升序唯一索引课程:对属性“课程编号”建立升序唯一索引开设情况:建立按“班级编号”升序排列的普通索引教师:对“教师编号”建立升序唯一索引学生:对“学号”建立升序唯一索引选修信息:建立按“学号”升序和“成绩”升序排列的普通索引
分区设计
根据磁盘分区设计的一般原则:
减少访问冲突,提高 I/O 并发性。多个事物并发访问同一磁盘时,会产生磁盘访问冲突而导致效率低下,如果事务访问数据均能分布于不同磁盘上,则I/O 可并发执行,从而提高数据库访问速度。
分散热点数据,均衡 I/O 负担。在数据库中数据访问的频率是不均匀的,那些经常被访问的数据成为热点数据,此类数据宜分散存在于不同的磁盘上,以均衡各个磁盘的负荷,充分发挥多磁盘的并行操作的优势。
保证关键数据快速访问,缓解系统瓶颈。在数据库中有些数据如数据字典等的访问频率很高,为保证对它的访问不直接影响整个系统的效率,可以将其存放在某一固定磁盘上,以保证其快速访问。
由于我们设计的系统数据量较小,因此不需要分区。
数据库实施
本实验的全部操作在 MySQL 中的查询语句中实现。
基本表建立
图 5.1.1 创建基本表”zhangcq_colleges15”
描述:zcq_Collegeno15 是主键。
图 5.1.2 创建基本表”zhangcq_Class15”
描述:zcq_Classno15 是主键。
建基本表”zhangcq_Major15”
描述:zcq_Mno15 是主键,zcq_Collegeno 是引用 zhangcq_College15 表的外键。
创建基本表”zhangcq_Teachers15”
描述:zcq_Tno 是主键,zcq_Collegeno15 是引用 zhangcq_College 的外键。
自定义完整性约束:zcq_Tage15 的范围是 0 到 100。Teacher_authority 的范围是 0-10,代表管理权限 的 10 个层级。Teachers_sex 只能是 M 或 F 代表男女。
图 5.1.5 创建基本表”zhangcq_Courses15”
描述: zcq_Courseno 是主键, zcq_Tno15 是引用 zhangcq_Teacher15 的外键。 zcq_Collegeno15 是引用 zhangcq_colleges15 的外键。自定义完整性约束:Courses_credit 的范围是 0 到 10,代表学分从 0 个到 10 个。
Courses_hours 的范围是 0-100,代表课程学时从 0 个到 100 个。Courses_assessment 只能是
“考察”或“考试”。
创建基本表”zhangcq_Students15”
描述:zcq_Sno 是主键,zcq_Mno15 是引用 zhangcq_Majors15 的外键。zcq_Classno15
是引用 zhangcq_Class15 的外键。自定义完整性约束:zcq_Savggpa15 的范围是 0 到 5,代表平均绩点从 0 个到 5。 zcq_Scredit15 的范围是 0-300,代表已修学分从 0 个到 300 个。zcq_Sage15 从 0-100,代表年龄从 0-100。zcq_Ssex15 只能是 M 或 F,代表男女。
图 5.1.7 创建基本表”zhangcq_Grade15”
描述:zcq_Sno15,zcq_Courseno15,zcq_Tno15 三个共同构成主键。自定义完整性约束:zcq_Grade15 的范围是 0-100,代表成绩从 0-100。
图 5.1.8 创建基本表”zhangcq_Setupinfo15” 描述:zcq_Classno15,zcq_Courseno15 两个共同构成主键。
视图的建立
以下视图都是为了提升用户体验而进行设计的,用户在进行查询时。如果只按照基本表中的信息给出的话,那些班级编号,课程编号,教师编号等用户会极难理解,所以利用视图将多个表中的字段提取出来,让后呈现给用户,提升用户体验。
图 5.2.1 创建视图”学生信息”
图 5.2.2 创建视图”教师信息”
图 5.2.3 创建视图”课程信息”
图 5.2.4 创建视图”课程开设信息”
图 5.2.5 创建视图”成绩清单信息”
图 5.2.6 创建视图”任教课程信息”
索引的建立
以下索引是为了方便系统更好的查找数据,提升搜索效率和速度。
图 5.3.1 创建索引“对班级编号唯一升序索引”
图 5.3.2 创建索引“对课程编号唯一升序索引”
图 5.3.3 创建索引“对教师编号唯一升序索引”
图 5.3.4 创建索引“对学生编号唯一升序索引”
触发器建立
图 5.4.1 创建触发器”自动更新学生学分” 描述:当教师录入这个学生的成绩时,这个触发器会被调用,从而根据学生的成绩表,对学生个人的已修学分这一数据项进行更新。
图 5.4.2 创建触发器”自动更新学生平均绩点”
描述:当教师录入这个学生的成绩时,这个触发器会被调用,从而根据学生的成绩表,对学生个人的平均绩点这一数据项进行更新。
图 5.4.3 创建触发器”删除学生成绩自动更新学分”
描述:当教师删除这个学生的成绩时,这个触发器会被调用,从而根据学生的成绩表,对学生个人的已修学分这一数据项进行更新。
图 5.4.4 创建触发器”删除学生成绩自动更新绩点”
描述:当教师删除这个学生的成绩时,这个触发器会被调用,从而根据学生的成绩表,对学生个人的平均绩点这一数据项进行更新。
建存储过程
图 5.5.1 创建存储过程”为一个班级的学生添加课程记录”
描述:当管理员想要为一个班级开课时,管理员会调用该存储过程,这个存储过程将会去学生表中检索出所有属于给定班级的学生,然后用游标的方式,将这些学生一一加入到成绩表中,这时他们的成绩是 null,说明教师还没有录入成绩。
图 5.5.2 创建存储过程”为所有老师学生年龄加一”
描述:当时间过完一年时,系统将会自动调用这个存储过程。这个存储过程会将学生和教师的年龄都自动的加上一。
应用系统开发与试运行
开发平台和开发环境介绍。
本实验由 IntelliJ IDEA 2020.3.3 x64 开发,运用了 javaBean,Servlet,DAO 等框架,由 Servlet 进行处理数据,并且设置了过滤器,以免用户使用权限不足的功能。数据库存储用了 MySQL 数据库。后台与数据库的连接主要通过数据池进行连接,它可以进一步提高并发的效率和速度。在前端 bootstrap 模板的基础上进行进一步的 UI 设计。最终,本款产品在 jdk8.0 的环境下,试运行成功。
前台界面与后台数据库连接说明,代码实现。
本实验采取 MySQL 数据库,由 Java 用数据源的方式进行链接。
<?xml version="1.0" encoding="utf-8"?>
<Context reloadable = "true">
<Resource name="jdbc/sampleDS" type="javax.sql.DataSource"
driverClassName="com.mysql.cj.jdbc.Driver"
url="jdbc:mysql://localhost:3306/zhangcqmis15?useUnicode=true&cha racterEncoding=utf-8&useSSL=false&serverTimezone = GMT"
username="root" password="zerostart" maxActive="400" maxIdle="20" maxWait="500"
/>
</Context>
首先,先在 context.xml 中配置好 MySQL 的相应信息,包括驱动 Driver 所在地, MySQL 链接账户名和密码,允许的最大链接数和最大等待时间。
之后,由 BaseDAO 负责建立链接并调用。其他 DAO 对 BaseDAO 进行继承就可以用 SQL 语句对数据库进行操作了。
package com.example.final_database.dao;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import java.sql.Connection;
public class Basedao {
DataSource dataSource;
public Basedao() {
try {
Context context = new InitialContext();
dataSource =
(DataSource)context.lookup("java:comp/env/jdbc/sampleDS");
} catch (NamingException ne) {
System.out.println("Exception:"+ne);
}
}
public Connection getConnection()throws Exception{ return dataSource.getConnection(); }
}
系统各功能设计和运行界面截图。
学生信息管理系统登录界面
图 6.3.1 学生成绩管理系统登录展示图
功能设计:在这个页面,用户填写好表单后交到后台进行审核,然后根据用户类型到相应的表中搜索账号密码,若账号密码输入正确。如果是学生则跳转到学生界面,如果是老师或管理员,也相应的跳转到对应界面。
后端代码:
package com.example.final_database.controller;
import com.example.final_database.dao.loginDao;
import com.example.final_database.model.Student;
import com.example.final_database.model.Teacher;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
@WebServlet(name = "loginServlet", value = "/loginServlet") public class loginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
}
@Override
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); //1
response.setContentType("text/html;charset=utf-8"); //2
response.setCharacterEncoding("utf-8"); //3
String kind =request.getParameter("kind");
String username = request.getParameter("username");
String password = request.getParameter("password");
HttpSession session=request.getSession();
String message=null;
RequestDispatcher dispatcher=null; loginDao userdao=new loginDao(); if(kind.equals("student")){
Student user=userdao.StudentLogin(username,password); if(user==null){
message="用户名或密码错误";
dispatcher=request.getRequestDispatcher("./VIEW/index.jsp");
}
else{
message="登录成功!欢迎!";
session.setAttribute("user",user);
dispatcher=request.getRequestDispatcher("./VIEW/student.jsp");
}
session.setAttribute("message",message); session.setAttribute("kind","学生"); dispatcher.forward(request,response);
}
else if(kind.equals("teacher")){
Teacher user=userdao.TeacherLogin(username,password); if(user==null){
message="用户名或密码错误";
dispatcher=request.getRequestDispatcher("./VIEW/index.jsp");
} else{
message="登录成功!欢迎!";
session.setAttribute("user",user); if(user.getTauthority()<2) { dispatcher =
request.getRequestDispatcher("./VIEW/teacher.jsp");
} else{ dispatcher =
request.getRequestDispatcher("./VIEW/admin.jsp");
}
}
session.setAttribute("message",message); session.setAttribute("kind","老师"); dispatcher.forward(request,response);
}
}
}
管理员
输入账号密码后,进行登录将会跳转到界面一。
界面一:学生管理界面
图 6.3.2.1 学生信息管理展示图:学生添加
图 6.3.2.2 学生信息管理展示图:学生查询
功能设计:这个界面一共有两个功能,一是学生添加,二是学生查询。学生
添加主要是通过表单交给后台,后台通过 INSERT 语句插入信息到相应的表中。学生查询则是通过 zhangcq_stuinfo15 视图进行 SELECT 查询,因为普通表中的字段都是编号,对管理人员使用十分不友善,所以专门新建了一个视图进行查询。
核心代码:
(学生添加)
public boolean addStudennt(String Sno,String Mno ,String Sname,String
Ssex,String Sage,String Savggpa,String Scredit,String Sphone,String
Shometown,String Spwd,String Classno) {
String sql = "INSERT INTO zhangcq_students15
VALUES(?,?,?,?,?,?,?,?,?,?,?)"; try (Connection conn = dataSource.getConnection();
PreparedStatement psmt = conn.prepareStatement(sql)) { psmt.setString(1,Sno); psmt.setString(2,Mno); psmt.setString(3,Sname); psmt.setString(4,Ssex); psmt.setInt(5,Integer.parseInt(Sage)); psmt.setDouble(6,Double.parseDouble(Savggpa)); psmt.setDouble(7,Double.parseDouble(Scredit)); psmt.setString(8,Sphone); psmt.setString(9,Shometown); psmt.setString(10,Spwd); psmt.setString(11,Classno); psmt.execute(); return true;
} catch (SQLException throwables) { throwables.printStackTrace();
return false;
}
}
学生查询:
public ArrayList<Student> queryStudent(String Sno, String Mno, String
Classname) {
String sql="select * from zhangcq_stuinfo15 WHERE 1=1";
if(!Sno.equals("")) {
sql=sql+" and zcq_Sno15='"+Sno+"'";
}
if(!Mno.equals("")) {
sql=sql+" and zcq_Mname15='"+Mno+"'";
}
if(!Classname.equals("")) {
sql=sql+" and zcq_Classname15='"+Classname+"'";
}
ArrayList<Student> list=new ArrayList<Student>();
try(Connection
conn=dataSource.getConnection(); PreparedStatement psmt=conn.prepareStatement(sql)) {
try(ResultSet rst = psmt.executeQuery()) {
while(rst.next()) {
Student student=new Student();
student.setSno(rst.getString(1));
student.setMajor(rst.getString(2));
student.setSname(rst.getString(3));
student.setSsex(rst.getString(4));
student.setBanji(rst.getString(5));
student.setSphone(rst.getString(6));
student.setShometown(rst.getString(7));
list.add(student);
}
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return list;
}
界面二:教师管理界面
图 6.3.2.3 教师信息管理展示图:教师添加
图 6.3.2.4 教师信息管理展示图:教师查询
功能设计:这个界面一共有两个功能,一是教师添加,二是教师查询。教师
添加主要是通过表单交给后台,后台通过 INSERT 语句插入信息到相应的表中。教师查询则是通过 zhangcq_teainfo15 视图进行 SELECT 查询,因为普通表中的字段都是编号,对管理人员使用十分不友善,所以专门新建了一个视图进行查询。
核心代码:
(教师添加)
PreparedStatement psmt = conn.prepareStatement(sql)) { psmt.setString(1,tno); psmt.setString(2,tname); psmt.setString(3,tsex); psmt.setString(4,tprofess); psmt.setInt(5,Integer.parseInt(tage)); psmt.setString(6,tphone); psmt.setInt(7,Integer.parseInt(tauthority)); psmt.setString(8,tpwd); psmt.setString(9,collegeno); psmt.execute(); return true;
} catch (SQLException throwables) { throwables.printStackTrace();
return false;
}
}
(教师查询)
public ArrayList<Teacher> queryTeacher(String Tno, String College,
String profess) {
String sql="select * from zhangcq_teainfo15 WHERE 1=1"; if(!Tno.equals("")){ sql=sql+" and zcq_Tno15='"+Tno+"'";
}
if(!College.equals("")){ sql=sql+" and zcq_Collegename15='"+College+"'";
}
if(!profess.equals("")){ sql=sql+" and zcq_Tprofess15='"+profess+"'";
}
ArrayList<Teacher> list=new ArrayList<Teacher>();
try(Connection conn=dataSource.getConnection();PreparedStatement
psmt=conn.prepareStatement(sql)){ try(ResultSet rst = psmt.executeQuery()){ while(rst.next()){
Teacher teacher=new Teacher(); teacher.setTno(rst.getString(1)); teacher.setTname(rst.getString(2)); teacher.setTsex(rst.getString(3)); teacher.setTprofess(rst.getString(4)); teacher.setTphone(rst.getString(5)); teacher.setTage(rst.getInt(6));
teacher.setCollegename(rst.getString(7)); list.add(teacher);
}
}
} catch (SQLException throwables) { throwables.printStackTrace();
}
return list;
}
界面三:课程管理界面
图 6.3.2.5 课程信息管理展示图:课程查询
图 6.3.2.6 课程信息管理展示图:课程查询
功能设计:这个界面一共有两个功能,一是课程添加,二是课程查询。课程
添加主要是通过表单交给后台,后台通过 INSERT 语句插入信息到相应的表中。课程查询则是通过 zhangcq_couinfo15 视图进行 SELECT 查询,因为普通表中的字段都是编号,对管理人员使用十分不友善,所以专门新建了一个视图进行查询。核心代码:
(课程添加)
public boolean addCourse(String Courseno,String Coursename,String
Collegeno,String Ccredit,String Chours,String Cassessment) {
String sql = "INSERT INTO zhangcq_courses15 VALUES(?,?,?,?,?,?)";
try (Connection conn = dataSource.getConnection();
PreparedStatement psmt = conn.prepareStatement(sql)) {
psmt.setString(1,Courseno);
psmt.setString(2,Coursename);
psmt.setString(3,Collegeno);
psmt.setDouble(4,Double.parseDouble(Ccredit));
psmt.setInt(5,Integer.parseInt(Chours));
psmt.setString(6,Cassessment);
psmt.execute();
return true;
} catch (SQLException throwables) {
throwables.printStackTrace();
return false;
}
}
(课程查询)
public ArrayList<Course> queryCourse(String Courseno, String
Collegename, String Cterm) {
String sql="select distinct * from zhangcq_couinfo15 WHERE 1=1"; if(!Courseno.equals("")){ sql=sql+" and zcq_Courseno15='"+Courseno+"'";
}
if(!Collegename.equals("")){ sql=sql+" and zcq_Collegename15='"+Collegename+"'";
}
if(!Cterm.equals("")){ sql=sql+" and zcq_Cterm15='"+Cterm+"'";
}
ArrayList<Course> list=new ArrayList<Course>();
try(Connection conn=dataSource.getConnection();PreparedStatement
psmt=conn.prepareStatement(sql)){ try(ResultSet rst = psmt.executeQuery()){ while(rst.next()){
Course course=new Course(); course.setCourseno(rst.getString(1)); course.setCoursename(rst.getString(2));
course.setCcredit(rst.getDouble(3)); course.setCterm(rst.getString(4)); course.setTname(rst.getString(5)); course.setCollegename(rst.getString(6)); course.setCassessment(rst.getString(7)); list.add(course);
}
}
} catch (SQLException throwables) { throwables.printStackTrace();
}
return list;
}
界面四:班级开课管理界面
图 6.3.2.7 开课信息信息管理展示图:班级开课
图 6.3.2.8 开课信息管理展示图:开课信息查询
功能设计:这个界面一共有两个功能,一是开课信息添加,二是开设课程信息查询。课程添加主要是通过表单交给后台,后台通过事先设计的存储过程 zcq_insertStu15,将班级中的每一个学生,新建信息到 zhangcq_grade15 表中。课程查询则是通过 zhangcq_setinfo15 视图进行 SELECT 查询,因为普通表中的字段都是编号,对管理人员使用十分不友善,所以专门新建了一个视图进行查询。核心代码
(开设课程)
public boolean addSetupinfo(String Courseno,String Classno,String
Tno,String Cterm) {
String sql = "INSERT INTO zhangcq_setupinfo15 VALUES(?,?)";
try (Connection conn = dataSource.getConnection();
PreparedStatement psmt = conn.prepareStatement(sql)) {
psmt.setString(1,Courseno);
psmt.setString(2,Classno);
psmt.execute();
return true;
} catch (SQLException throwables) {
throwables.printStackTrace();
return false;
}
}
public boolean addSetupinfo1(String Courseno,String Classno,String
Tno,String Cterm) {
String sql = "CALL zcq_insertStu15(?,?,?,?);";
try (Connection conn = dataSource.getConnection();
PreparedStatement psmt = conn.prepareStatement(sql)) {
psmt.setString(1,Courseno);
psmt.setString(2,Classno);
psmt.setString(3,Tno);
psmt.setString(4,Cterm);
psmt.execute();
return true;
} catch (SQLException throwables) {
throwables.printStackTrace();
return false;
}
}
(查询课程)
public ArrayList<Setupinfo> querySetup(String Coursename, String
Classname) {
String sql="select distinct * from zhangcq_setinfo15 WHERE 1=1"; if(!Coursename.equals("")){ sql=sql+" and zcq_Coursename15='"+Coursename+"'";
}
if(!Classname.equals("")){ sql=sql+" and zcq_Classname15='"+Classname+"'";
}
ArrayList<Setupinfo> list=new ArrayList<Setupinfo>();
try(Connection conn=dataSource.getConnection();PreparedStatement
psmt=conn.prepareStatement(sql)){ try(ResultSet rst = psmt.executeQuery()){ while(rst.next()){
Setupinfo setupinfo=new Setupinfo(); setupinfo.setCoursename(rst.getString(1)); setupinfo.setClassname(rst.getString(2)); list.add(setupinfo);
}
}
} catch (SQLException throwables) { throwables.printStackTrace();
}
return list;
}
界面五:学生成绩管理(仅查看)
图 6.3.2.9 学生成绩管理展示图:学生成绩信息查询
功能设计:这个界面就一个学生成绩查询功能。学生成绩查询则是通过 zhangcq_grainfo15 视图进行 SELECT 查询,因为普通表中的字段都是编号,对管理人员使用十分不友善,所以专门新建了一个视图进行查询。
核心代码:
public ArrayList<Grade> queryGrade(String sno,String cterm,String tno) {
String sql="select distinct * from zhangcq_grainfo15 WHERE 1=1"; if(!sno.equals("")){ sql=sql+" and zcq_Sno15='"+sno+"'";
}
if(!cterm.equals("")){ sql=sql+" and zcq_Cterm15='"+cterm+"'";
}
if(!tno.equals("")){ sql=sql+" and zcq_Tno15='"+tno+"'";
}
ArrayList<Grade> list=new ArrayList<Grade>();
try(Connection conn=dataSource.getConnection();PreparedStatement
psmt=conn.prepareStatement(sql)){ try(ResultSet rst = psmt.executeQuery()){ while(rst.next()){
Grade grade=new Grade(); grade.setSno(rst.getString(1)); grade.setSname(rst.getString(2));
grade.setCoursename(rst.getString(3)); grade.setGrade(rst.getInt(4)); grade.setTno(rst.getString(5)); grade.setTname(rst.getString(6)); grade.setCterm(rst.getString(7)); list.add(grade);
}
}
} catch (SQLException throwables) { throwables.printStackTrace();
}
return list;
}
界面六:学院信息管理
图 6.3.2.10 学院管理展示图:学院信息添加
图 6.3.2.11 学院管理展示图:学院信息查询
功能设计:这个界面一共有两个功能,一是学院添加,二是学院查询。学院
添加主要是通过表单交给后台,后台通过 INSERT 语句插入信息到相应的表中。
学院查询则是通过直接 SELECT 表 zhangcq_colleges15 得到查询结果。
核心代码:
(学院添加)
public boolean addCollege(String Collegeno,String Collegename) {
String sql = "INSERT INTO zhangcq_colleges15 VALUES(?,?)";
try (Connection conn = dataSource.getConnection();
PreparedStatement psmt = conn.prepareStatement(sql)) {
psmt.setString(1,Collegeno);
psmt.setString(2,Collegename);
psmt.execute();
return true;
} catch (SQLException throwables) {
throwables.printStackTrace();
return false;
}
}
(学院查询)
public ArrayList<College> queryCollege() {
String sql="select * from zhangcq_colleges15";
ArrayList<College> list=new ArrayList<College>();
try(Connection conn=dataSource.getConnection(); PreparedStatement
psmt=conn.prepareStatement(sql)) {
try(ResultSet rst = psmt.executeQuery()) {
while(rst.next()) {
College college = new College();
college.setCollegeno(rst.getString(1));
college.setCollegename(rst.getString(2));
list.add(college);
}
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return list;
}
界面七:专业信息管理
图 6.3.2.11 专业管理展示图:专业信息添加
图 6.3.2.12 专业管理展示图:专业信息查询
- 功能设计:这个界面一共有两个功能,一是专业添加,二是专业查询。专业
- 添加主要是通过表单交给后台,后台通过 INSERT 语句插入信息到相应的表中。
- 专业查询则是通过直接 SELECT 表 zhangcq_majors15 得到查询结果。
核心代码:
(专业添加)
public boolean addMajor(String Mno,String Mname,String Collegeno) { String sql = "INSERT INTO zhangcq_majors15 VALUES(?,?,?)"; try (Connection conn = dataSource.getConnection();
PreparedStatement psmt = conn.prepareStatement(sql)) { psmt.setString(1,Mno); psmt.setString(2,Mname); psmt.setString(3,Collegeno);
psmt.execute(); return true;
} catch (SQLException throwables) { throwables.printStackTrace();
return false;
}
}
(专业查询)
public ArrayList<Major> queryMajor() {
String sql="select * from zhangcq_majors15";
ArrayList<Major> list=new ArrayList<Major>();
try(Connection conn=dataSource.getConnection(); PreparedStatement
psmt=conn.prepareStatement(sql)) {
try(ResultSet rst = psmt.executeQuery()) {
while(rst.next()) {
Major major = new Major();
major.setMno(rst.getString(1));
major.setMname(rst.getString(2));
major.setCollegeno(rst.getString(3));
list.add(major);
}
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return list;
}
界面八:班级信息管理
图 6.3.2.13 班级管理展示图:班级信息添加
图 6.3.2.14 班级管理展示图:班级信息查询
功能设计:这个界面一共有两个功能,一是班级添加,二是班级查询。班级
添加主要是通过表单交给后台,后台通过 INSERT 语句插入信息到相应的表中。
班级查询则是通过直接 SELECT 表 zhangcq_class15 得到查询结果。
核心代码:
(班级添加)
public boolean addClass(String Classno,String Classname) {
String sql = "INSERT INTO zhangcq_class15 VALUES(?,?)";
try (Connection conn = dataSource.getConnection();
PreparedStatement psmt = conn.prepareStatement(sql)) {
psmt.setString(1,Classno);
psmt.setString(2,Classname);
psmt.execute();
return true;
} catch (SQLException throwables) {
throwables.printStackTrace();
return false;
}
}
(班级查询)
public ArrayList<Banji> queryClass(){
String sql="select * from zhangcq_class15";
ArrayList<Banji> list=new ArrayList<Banji>();
try(Connection conn=dataSource.getConnection();PreparedStatement
psmt=conn.prepareStatement(sql)){ try(ResultSet rst = psmt.executeQuery()){ while(rst.next()){
Banji banji = new Banji(); banji.setClassno(rst.getString(1)); banji.setClassname(rst.getString(2)); list.add(banji);
}
}
} catch (SQLException throwables) { throwables.printStackTrace();
}
return list;
}
教师
界面一:成绩录入
图 6.3.3.1 录入成绩列表
图 6.3.3.2 录入成绩模态框
功能设计:这个页面主要功能就是根据查询的课程名和班级查,列出所有符合条件的学生,前提是任课教师是登录账号的教师。然后教师可以通过输入成绩模态框,对他们的成绩进行输入和修改。
核心代码:
(查询成绩)
public ArrayList<Grade> insertGrade1(String tno,String coursename,String banji) {
String sql="select distinct * from zhangcq_grainfo15 WHERE 1=1"; if(!coursename.equals("")){ sql=sql+" and zcq_Coursename15='"+coursename+"'";
}
if(!banji.equals("")){ sql=sql+" and zcq_Classname15='"+banji+"'";
}
if(!tno.equals("")){ sql=sql+" and zcq_Tno15='"+tno+"'";
}
ArrayList<Grade> list=new ArrayList<Grade>();
try(Connection conn=dataSource.getConnection();PreparedStatement
psmt=conn.prepareStatement(sql)){ try(ResultSet rst = psmt.executeQuery()){ while(rst.next()){
Grade grade=new Grade(); grade.setSno(rst.getString(1)); grade.setSname(rst.getString(2)); grade.setCoursename(rst.getString(3)); grade.setGrade(rst.getInt(4)); grade.setTno(rst.getString(5)); grade.setTname(rst.getString(6));
grade.setCterm(rst.getString(7)); grade.setClassname(rst.getString(8)); grade.setCno(rst.getString(9)); list.add(grade);
}
}
} catch (SQLException throwables) { throwables.printStackTrace();
}
return list;
}
(录入成绩)
public boolean modify_grade(String sno,String tno,String cno,String cterm,String grade) {
String sql = "UPDATE zhangcq_grade15 SET zcq_Grade15 = ? WHERE zcq_Sno15 = ? and zcq_Tno15 = ? and zcq_Courseno15 = ? and zcq_Cterm15
= ?"; try (Connection conn = dataSource.getConnection();
PreparedStatement psmt = conn.prepareStatement(sql)) {
psmt.setInt(1,Integer.parseInt(grade));
psmt.setString(2,sno);
psmt.setString(3,tno);
psmt.setString(4,cno);
psmt.setString(5,cterm);
psmt.execute();
return true;
} catch (SQLException throwables) {
throwables.printStackTrace();
return false;
}
}
界面二:成绩查询
图 6.3.3.3 教师查询对应任教学生成绩
图 6.3.3.4 教师查询对应任教学生成绩饼状图
功能设计:这个页面主要功能就是根据查询的课程名和上课学期查,列出所有符合条件的学生,前提是任课教师是登录账号的教师。然后教师就可以知道他们的成绩的具体分布。
核心代码:
public ArrayList<Grade> t_queryGrade(String coursename,String cterm,String tno) {
String sql="select distinct * from zhangcq_grainfo15 WHERE 1=1"; if(!coursename.equals("")){ sql=sql+" and zcq_Coursename15='"+coursename+"'";
}
if(!cterm.equals("")){ sql=sql+" and zcq_Cterm15='"+cterm+"'";
}
if(!tno.equals("")){ sql=sql+" and zcq_Tno15='"+tno+"'";
}
ArrayList<Grade> list=new ArrayList<Grade>();
Grade.setNine(0);
Grade.setEight(0);
Grade.setSeven(0);
Grade.setSix(0);
Grade.setDown(0);
try(Connection conn=dataSource.getConnection();PreparedStatement
psmt=conn.prepareStatement(sql)){ try(ResultSet rst = psmt.executeQuery()){ while(rst.next()){
Grade grade=new Grade(); grade.setSno(rst.getString(1)); grade.setSname(rst.getString(2)); grade.setCoursename(rst.getString(3)); grade.setGrade(rst.getInt(4)); grade.setTno(rst.getString(5)); grade.setTname(rst.getString(6)); grade.setCterm(rst.getString(7)); if(grade.getGrade()>90){
Grade.setNine(Grade.getNine()+1);
}
else if(grade.getGrade()>80){
Grade.setEight(Grade.getEight()+1);
}
else if(grade.getGrade()>70){
Grade.setSeven(Grade.getSeven()+1);
}
else if(grade.getGrade()>60){
Grade.setSix(Grade.getSix()+1);
}
else if(grade.getGrade()<60 && grade.getGrade()>0){ Grade.setDown(Grade.getDown()+1);
}
list.add(grade);
}
}
} catch (SQLException throwables) { throwables.printStackTrace();
}
return list;
}
界面三:任课查询
图 6.3.3.5 教师查询任教课程
功能设计:这个页面主要功能就是根据查询的上课学期查,列出所有符合条件的课程,前提是任课教师是登录账号的教师。然后教师就可以知道这个学期的具体任教课程信息。
核心代码:
public ArrayList<Grade> queryWork(String tno,String cterm){
String sql="select distinct zcq_Cterm15, zcq_Coursename15, zcq_Chours15, zcq_Cassessment15 from zhangcq_workinfo15 WHERE 1=1"; if(!tno.equals("")){ sql=sql+" and zcq_Tno15='"+tno+"'";
}
if(!cterm.equals("")){ sql=sql+" and zcq_Cterm15='"+cterm+"'";
}
ArrayList<Grade> list=new ArrayList<Grade>();
try(Connection conn=dataSource.getConnection();PreparedStatement
psmt=conn.prepareStatement(sql)){ try(ResultSet rst = psmt.executeQuery()){ while(rst.next()){
Grade grade = new Grade(); grade.setCterm(rst.getString(1)); grade.setCoursename(rst.getString(2)); grade.setChour(rst.getInt(3)); grade.setAssessment(rst.getString(4)); list.add(grade);
}
}
} catch (SQLException throwables) { throwables.printStackTrace();
}
return list;
}
界面四:修改密码
图 6.3.3.6 教师修改密码界面
功能设计:这个页面主要功能就是修改教师密码。根据教师输入的旧密码是否一致保证安全,然后进行新密码修改。
核心代码:
public boolean modify_pwd(String new_pwd,String tno) {
String sql = "UPDATE zhangcq_teachers15 SET zcq_Tpwd15 = ? WHERE zcq_Tno15 = ?";
try (Connection conn = dataSource.getConnection();
PreparedStatement psmt = conn.prepareStatement(sql)) {
psmt.setString(1,new_pwd);
psmt.setString(2,tno);
psmt.execute();
return true;
} catch (SQLException throwables) {
throwables.printStackTrace();
return false;
}
}
学生
界面一:成绩查询
图 6.3.4.1 学生成绩查询图
功能设计:这个页面主要功能就是根据查询的上课学期查,列出所有符合条件的成绩,前提是学生信息是登录账号的学生。然后学生就可以知道这个学期的具体的课程成绩信息。
核心代码:
public ArrayList<Grade> queryGrade(String sno,String cterm,String tno)
{
String sql="select distinct * from zhangcq_grainfo15 WHERE 1=1"; if(!sno.equals("")){ sql=sql+" and zcq_Sno15='"+sno+"'";
}
if(!cterm.equals("")){ sql=sql+" and zcq_Cterm15='"+cterm+"'";
}
if(!tno.equals("")){ sql=sql+" and zcq_Tno15='"+tno+"'";
}
ArrayList<Grade> list=new ArrayList<Grade>();
try(Connection conn=dataSource.getConnection();PreparedStatement
psmt=conn.prepareStatement(sql)){ try(ResultSet rst = psmt.executeQuery()){ while(rst.next()){
Grade grade=new Grade(); grade.setSno(rst.getString(1)); grade.setSname(rst.getString(2)); grade.setCoursename(rst.getString(3)); grade.setGrade(rst.getInt(4)); grade.setTno(rst.getString(5)); grade.setTname(rst.getString(6)); grade.setCterm(rst.getString(7)); list.add(grade);
}
}
} catch (SQLException throwables) { throwables.printStackTrace();
}
return list;
}
界面二:课程查询
图 6.3.4.2 学生课程查询界面
功能设计:这个页面主要功能就是根据查询的上课学期查,列出所有符合条件的课程,前提是学生信息是登录账号的学生。然后学生就可以知道这个学期的具体的课程信息。
核心代码:
public ArrayList<Grade> queryWork(String sno,String cterm)
{ String sql="select * from zhangcq_workinfo15 WHERE 1=1";
if(!sno.equals("")){ sql=sql+" and zcq_Sno15='"+sno+"'";
}
if(!cterm.equals("")){ sql=sql+" and zcq_Cterm15='"+cterm+"'";
}
ArrayList<Grade> list=new ArrayList<Grade>();
try(Connection conn=dataSource.getConnection();PreparedStatement
psmt=conn.prepareStatement(sql)){ try(ResultSet rst = psmt.executeQuery()){ while(rst.next()){
Grade grade = new Grade(); grade.setCterm(rst.getString(4)); grade.setCoursename(rst.getString(5)); grade.setCredit(rst.getDouble(6)); grade.setTname(rst.getString(3)); grade.setAssessment(rst.getString(8)); list.add(grade);
}
}
} catch (SQLException throwables) { throwables.printStackTrace();
}
return list;
}
界面三:教学计划查询
图 6.3.4.3 学生教学计划查询界面
功能设计:就是取出登录账号的已修学分和平均绩点。这些数据是教师在输入成绩的时候,根据先前设置的触发器马上进行实时更新的。
核心代码:
request.setCharacterEncoding("utf-8"); //1 response.setContentType("text/html;charset=utf-8"); response.setCharacterEncoding("utf-8"); //3;String kind =request.getParameter("kind");;String username = request.getParameter("username");;String password = request.getParameter("password");;HttpSession session=request.getSession();
String message=null;
RequestDispatcher dispatcher=null;
loginDao userdao=new loginDao();
if(kind.equals("student")) {
Student user=userdao.StudentLogin(username,password);
if(user==null) {
message="用户名或密码错误";
dispatcher=request.getRequestDispatcher("./VIEW/index.jsp");
}
else {
message="登录成功!欢迎!";
session.setAttribute("user",user);
dispatcher=request.getRequestDispatcher("./VIEW/student.jsp")
}
session.setAttribute("message",message);
session.setAttribute("kind","学生");
dispatcher.forward(request,response);
}
;
界面四:修改密码
图 6.3.4.4 学生修改密码界面
功能设计:这个页面主要功能就是修改教师密码。根据教师输入的旧密码是否一致保证安全,然后进行新密码修改。
核心代码:
public boolean modify_pwd(String new_pwd,String tno)
{
String sql = "UPDATE zhangcq_teachers15 SET zcq_Tpwd15 = ? WHERE
zcq_Tno15 = ?"; try (Connection conn = dataSource.getConnection();
PreparedStatement psmt = conn.prepareStatement(sql))
{
psmt.setString(1,new_pwd); psmt.setString(2,tno); psmt.execute(); return true;
} catch (SQLException throwables) { throwables.printStackTrace();
return false;
}
}
访问无权限页面时
图 6.3.5.1 访问无权页面展示图
实验总结
遇到的问题和解决的办法
在表中,我们使用编号来代表专业、学院、班级、课程,但是这些在查询时直接展现给用户就会显得很不友好。但如果要用名字代表,用原来表字段创建的模型就会失效。
所以我们在原来的基础上扩充模型,虽然会有一定的冗余,但大大提升了用
户的可操作性,和减少了代码的编写量。
当前端用户查询时输入了空字符串,此时其实是用户不希望用这个查询条件的,但按我们平时的代码的话,就会查询到空结果。于是我们希望将空字符串查询到的结果为全部。
实现过程如下,
string sql="select * from 表 where 1=1" 查询表里所有内容
它增加 1=1 的目的来了,是为下面的拼凑做准备.
if(username!="") {sql=sql+" and username='admin'";} //查询用户名为 admin 的用户 if(password!="") {sql=sql+" and password='123'"}
//查询用户名为 admin,密码为 123 的用户
当用课程和成绩表联合查询时会出现许多重复项,这个时候会影响用户的搜索效率,于是我再查询语句的主字段前加了 distinct 有效的删除了视图中的重复项。
在创建存储过程的时候一直报 1064 的错误,后来才知道,MySQL 解释器一碰到;就自动停止了。但是存储过程中避免不了有很多的“;”。所以我们要在开头用 delimiter$ undefined $这样 MySQL 遇到 $$ 就不会停止了。
在调运插入存储过程的时候,他总是会在最后一个地方报 1062 主键重复的错误。后来大量查阅资料发现必须要将 FETCH 放在判断之前才不会重复取值,而我之前用的 REPEAT 函数中的 UTIL 判断是永远在最开始执行的。导致最后一个元组取值重复。之后我就把 REPEATE 函数用 LOOP 代替,大功告成!
系统设计的不足
不同类型的用户登录这个系统会有不同的操作界面。但是为了防止一些用户恶意访问其他不属于自己权限的界面,本实验采取了修改链接的方式。但是一些内部用户仍可通过 get 方式直接访问越权界面。
在表的设计中,为了兼顾课程需要,本实验不能很好的表示选修课的班级状态,本实验的班级为实际的行政班,而并非现实生活中的走读班。实际上我们每个人都属于很多不同的班级。这点本实验没有考虑周全。
进一步改进思路和体会
如果有时间的话,我想用过滤器进行用户过滤用户访问请求会更加的合理和安全。
之后可以将表进行进一步的修改拆分,把班级单独进行表示。让每个学生可以属于不同的班级,每个班级可以拥有很多不同的学生。