简介
本文基于Spring5框架实现一个简单的学生成绩管理系统。它使用Druid
数据库连接池,以及Spring提供的JdbcTemplate
模板,实现Dao层和Service层的基本功能。
完整代码见github
https://github.com/AsajuHuishi/StudentScoreManagementSystemSpring
任务

环境依赖
JDK 1.8
MySQL 5.5.15
JDBC 5.1.49
Spring 5.2.6
Intellij IDEA 2020.3.1
- 所需依赖:

相关工作
MySQL+java: 实现学生成绩管理系统(1.0版本)
MySQL+java: 实现学生成绩管理系统(2.0版本)
本项目基于以上项目进行改进。主要改进内容有:
- 将结构分成Sevice和Dao两层,对冗余代码进行简化;
- 使用Druid数据库连接池技术;
- 应用JdbcTemplate模板封装增删改查SQL语句;
- 使用xml方式和注解方式实现IOC的bean管理。
项目结构

文件 | 功能 |
---|---|
StuScore.java | 实体类,建立和stu_score表相同的字段 |
StuDao.java | Dao层,数据库相关操作方法接口 |
StuDaoImpl.java | Dao层接口实现类,封装数据库连接,增删改查语句 |
StuService.java | Service层,实现具体业务操作(菜单) |
TestMenu.java | 测试主方法 |
bean.xml | 配置文件,配置Druid 数据库连接池+JdbcTemplate |
具体实现
使用MySQL生成表
包括 学号,姓名,成绩,班级四个字段。
USE db58;
DROP TABLE IF EXISTS stu_score;
CREATE TABLE IF NOT EXISTS stu_score(
NO VARCHAR(10) unique,
NAME VARCHAR(20),
score FLOAT,
className INT
);
DESC stu_score;
配置文件
prop.driverClassName=com.mysql.jdbc.Driver
prop.url=jdbc:mysql://localhost:3306/db58
prop.username=root
prop.password=123456
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--开启组件扫描-->
<context:component-scan base-package="indi.huishi.studentscore"></context:component-scan>
<!--数据库连接池属性文件-->
<context:property-placeholder location="jdbc.properties"/>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${prop.driverClassName}"></property>
<property name="password" value="${prop.password}"></property>
<property name="username" value="${prop.username}"></property>
<property name="url" value="${prop.url}"></property>
</bean>
<!--创建JdbcTemplate对象-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
</beans>
实体类
package indi.huishi.studentscore.entity;
public class StuScore {
public StuScore(String no, String name, float score, int className) {
this.no = no;
this.name = name;
this.score = score;
this.className = className;
}
public StuScore() {
}
/**
* 学生实体类,属性:姓名,学号,成绩,班级
*/
private String no;
private String name;
private float score;
private int className;
@Override
public String toString() {
return "StuScore{" +
"no='" + no + '\'' +
", name='" + name + '\'' +
", score=" + score +
", className=" + className +
'}';
}
public String getNo() {
return no;
}
public void setNo(String no) {
this.no = no;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public float getScore() {
return score;
}
public void setScore(float score) {
this.score = score;
}
public int getClassName() {
return className;
}
public void setClassName(int className) {
this.className = className;
}
}
数据访问层
接口
package indi.huishi.studentscore.dao;
import indi.huishi.studentscore.entity.StuScore;
import java.util.List;
public interface StuDao {
/** dao接口,实现以下方法:
* 数据库连接池的连接+增/删/改/查通用方法
*/
void add(StuScore stuScore);
void delete(String no);
void update(StuScore stuScore);
StuScore queryByName(String name);
StuScore queryByNo(String no);
void querySort();
List<Object> statistics();
}
接口实现类
package indi.huishi.studentscore.dao;
import indi.huishi.studentscore.entity.StuScore;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Repository
public class StuDaoImpl implements StuDao{
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public void add(StuScore stuScore) {
/**
* 增加学生记录
*/
Object[] params = {
stuScore.getNo(),stuScore.getName(),stuScore.getScore(),stuScore.getClassName()};
int add = 0;
try {
add = jdbcTemplate.update("insert into stu_score values(?,?,?,?)", params);
} catch (DataAccessException e) {
e.printStackTrace();
} finally {
System.out.println(add > 0 ? "添加成功" : "添加失败");
}
}
@Override
public void delete(String no) {
/**
* 按学号删除记录
*/
int delete = 0;
try {
delete = jdbcTemplate.update("delete from stu_score where no=?",no);
} catch (DataAccessException e) {
e.printStackTrace();
} finally {
System.out.println(delete > 0 ? "删除成功" : "删除失败");
}
}
@Override
public void update(StuScore stuScore) {
/**
* 按学号修改记录
*/
Object[] params = {
stuScore.getName(),stuScore.getScore(),stuScore.getClassName(),stuScore.getNo()};
int update = 0;
try {
update = jdbcTemplate.update("update stu_score set name=?,score=?,className=? where no=?",params);
} catch (DataAccessException e) {
e.printStackTrace();
} finally {
System.out.println(update > 0 ? "修改成功" : "修改失败");
}
}
@Override
public StuScore queryByName(String name) {
/**
* 按姓名查询记录
*/
StuScore stuScore = null;
try {
stuScore = jdbcTemplate.queryForObject("select * from stu_score where name=?", new BeanPropertyRowMapper<>(StuScore.class), name);
} catch (DataAccessException e) {
e.printStackTrace();
} finally {
return stuScore;
}
}
@Override
public StuScore queryByNo(String no) {
/**
* 按学号查询记录
*/
StuScore stuScore = null;
try {
stuScore = jdbcTemplate.queryForObject("select * from stu_score where no=?", new BeanPropertyRowMapper<>(StuScore.class), no);
} catch (DataAccessException e) {
e.printStackTrace();
} finally {
return stuScore;
}
}
@Override
public void querySort() {
/**
* 按C语言成绩排序
*/
List<StuScore> result = null;
try {
result = jdbcTemplate.query("select * from stu_score order by score",new BeanPropertyRowMapper<>(StuScore.class));
} catch (DataAccessException e) {
e.printStackTrace();
}
for (StuScore res:result) {
System.out.println(res.toString());
}
}
@Override
public List<Object> statistics() {
/**
* 统计
*/
List<Object> result = null;//保存集合的列表
String sql="select count(*),max(score),min(score),round(avg(score),4),className from stu_score group by className order by avg(score) desc";
try {
result = jdbcTemplate.query(sql, new RowMapper() {
@Override
public Object mapRow(ResultSet resultSet, int i) throws SQLException {
Map<String,Object> map = new HashMap<>();
map.put("count", resultSet.getObject(1));
map.put("max_score", resultSet.getObject(2));
map.put("min_score", resultSet.getObject(3));
map.put("avg_score", resultSet.getObject(4));
map.put("className", resultSet.getObject(5));
return map;
}
});
} catch (DataAccessException e) {
e.printStackTrace();
} finally {
return result;
}
}
}
业务逻辑层
实现菜单功能
package indi.huishi.studentscore.service;
import indi.huishi.studentscore.dao.StuDao;
import indi.huishi.studentscore.entity.StuScore;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
@Service
public class StuService {
@Autowired
private StuDao stuDao;
private static Scanner s;
private StuScore stuScore;
public void menu() {
//菜单
int choose,choose2;
List<Integer> chos = new ArrayList<Integer>();
for (int i=1;i<8;i++) {
chos.add(i);
}
Set<Integer> chooseSet = new HashSet<Integer>(chos);
do {
System.out.println("=======欢迎进入学生成绩管理系统=======");
System.out.println("1.新增学生记录");
System.out.println("2.修改学生记录");
System.out.println("3.删除学生记录");
System.out.println("4.按姓名或学号查询学生记录");
System.out.println("5.按成绩排序");
System.out.println("6.分班级统计");
System.out.println("7.退出");
System.out.println("请选择(1-7):");
Scanner scanner = new Scanner(System.in);
choose = scanner.nextInt();
while (!chooseSet.contains(choose)) {
System.out.println("请选择(1-7):");
choose = scanner.nextInt();
}
System.out.println("******************************");
switch (choose) {
case 1:
myAdd(); //菜单选择1,是新增学生
break;
case 2:
myUpdate(); //菜单选择2,是修改学生
break;
case 3:
myDel(); //菜单选择3,是删除学生
break;
case 4: //菜单选择4,是查询学生
System.out.print("请选择按姓名查询还是按照学号查询(1姓名 2学号):");
Scanner sc2 = new Scanner(System.in);
choose2 = sc2.nextInt();
if (choose2==1) {
myListByName();
}else if (choose2==2) {
myListByNo();
}
break;
case 5: //菜单选择5,按成绩排序
mySort();
break;
case 6: //菜单选择6,统计
myStatistic();
break;
case 7: //菜单选择7,是退出该系统
System.out.println("您选择了退出系统,确定要退出吗?(y/n)");
Scanner sc3 = new Scanner(System.in);
String scanExit = sc3.next();
if(scanExit.equals("y")){
System.exit(-1);
System.out.println("您已成功退出系统,欢迎您再次使用!");
}
break;
default:
break;
}
} while (choose!=7);
}
//新增学生信息
public void myAdd() {
String continute;
do {
s = new Scanner(System.in);
String no, name;
float score;
int className;
System.out.println("====新增学生====");
System.out.println("学号(长度不超过10):");
no = s.next();
System.out.println("班级(整数):");
className = s.nextInt();
System.out.println("姓名:");
name = s.next();
System.out.println("成绩:");
score = s.nextFloat();
//调用StuScoreOperation
stuDao.add(new StuScore(no, name, score, className));
System.out.println("是否继续添加(y/n):");
s = new Scanner(System.in);
continute = s.next();
} while (continute.equals("y"));
}
//修改学生信息
public void myUpdate(){
s = new Scanner(System.in);
String no;
System.out.println("====修改学生====");
System.out.println("请输入要修改的学生学号:");
no = s.next();
stuScore = stuDao.queryByNo(no);
if(stuScore!=null) {
System.out.println("查询到该姓名记录");
System.out.println(stuScore.toString());
System.out.println("请输入新的学生信息:");
s = new Scanner(System.in);
String name;
float score;
int className;
System.out.println("学生班级:");
className = s.nextInt();
System.out.println("学生姓名:");
name = s.next();
System.out.println("学生成绩:");
score = s.nextFloat();
stuDao.update(new StuScore(no, name, score, className));
}else{
System.out.println("未查询到该学号记录");
}
}
//删除学生信息
public void myDel(){
s = new Scanner(System.in);
String no;
System.out.println("====删除学生====");
System.out.println("请输入要删除的学生学号:");
no = s.next();
stuScore = stuDao.queryByNo(no);
if(stuScore!=null) {
System.out.println(stuScore.toString());
System.out.println("是否真的删除(y/n):");
s = new Scanner(System.in);
String x = s.next();
if (x.equals("y")) {
stuDao.delete(no);
}
}else{
System.out.println("未查询到该姓名记录");
}
}
//按姓名查询学生信息
public void myListByName(){
s = new Scanner(System.in);
System.out.println("====查询学生====");
System.out.println("请输入要查看的学生姓名:");
StuScore stuScore = stuDao.queryByName(s.next());
if(stuScore!=null) {
System.out.println("查询到该姓名记录");
System.out.println(stuScore.toString());
}else{
System.out.println("未查询到该姓名记录");
}
}
//按学号查询学生信息
public void myListByNo(){
s = new Scanner(System.in);
System.out.println("====查询学生====");
System.out.println("请输入要查看的学生学号:");
StuScore stuScore = stuDao.queryByNo(s.next());
if(stuScore!=null) {
System.out.println("查询到该学号记录");
System.out.println(stuScore.toString());
}else{
System.out.println("未查询到该学号记录");
}
}
//排序
public void mySort() {
System.out.println("按成绩升序显示");
System.out.println("学号\t\t班级\t姓名\t成绩");
stuDao.querySort();
}
//统计
public void myStatistic() {
System.out.println("统计(分班级统计学生数量,最高分,最低分,平均值)");
List<Object> result = stuDao.statistics();
for (Object obj:result){
System.out.println(obj.toString());
}
}
}
测试
package indi.huishi.studentscore.test;
import indi.huishi.studentscore.service.StuService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestMenu {
/**
* 测试
*/
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
StuService stuService = context.getBean("stuService", StuService.class);
stuService.menu();
}
}
实现结果
=======欢迎进入学生成绩管理系统=======
1.新增学生记录
2.修改学生记录
3.删除学生记录
4.按姓名或学号查询学生记录
5.按成绩排序
6.分班级统计
7.退出
请选择(1-7):
1
******************************
====新增学生====
学号(长度不超过10):
201
班级(整数):
1
姓名:
M7
成绩:
82
一月 19, 2021 3:53:26 下午 com.alibaba.druid.support.logging.JakartaCommonsLoggingImpl info
信息: {
dataSource-1} inited
添加成功
是否继续添加(y/n):
y
====新增学生====
学号(长度不超过10):
202
班级(整数):
2
姓名:
4D
成绩:
81
添加成功
是否继续添加(y/n):
y
====新增学生====
学号(长度不超过10):
203
班级(整数):
3
姓名:
A20
成绩:
84
添加成功
是否继续添加(y/n):
y
====新增学生====
学号(长度不超过10):
213
班级(整数):
3
姓名:
A32
成绩:
85
添加成功
是否继续添加(y/n):
y
====新增学生====
学号(长度不超过10):
212
班级(整数):
2
姓名:
38tnA
成绩:
86
添加成功
是否继续添加(y/n):
n
=======欢迎进入学生成绩管理系统=======
1.新增学生记录
2.修改学生记录
3.删除学生记录
4.按姓名或学号查询学生记录
5.按成绩排序
6.分班级统计
7.退出
请选择(1-7):
2
******************************
====修改学生====
请输入要修改的学生学号:
202
查询到该姓名记录
StuScore{
no='202', name='4D', score=81.0, className=2}
请输入新的学生信息:
学生班级:
2
学生姓名:
4D
学生成绩:
82.5
修改成功
=======欢迎进入学生成绩管理系统=======
1.新增学生记录
2.修改学生记录
3.删除学生记录
4.按姓名或学号查询学生记录
5.按成绩排序
6.分班级统计
7.退出
请选择(1-7):
3
******************************
====删除学生====
请输入要删除的学生学号:
213
StuScore{
no='213', name='A32', score=85.0, className=3}
是否真的删除(y/n):
y
删除成功
=======欢迎进入学生成绩管理系统=======
1.新增学生记录
2.修改学生记录
3.删除学生记录
4.按姓名或学号查询学生记录
5.按成绩排序
6.分班级统计
7.退出
请选择(1-7):
4
******************************
请选择按姓名查询还是按照学号查询(1姓名 2学号):1
====查询学生====
请输入要查看的学生姓名:
M7
查询到该姓名记录
StuScore{
no='201', name='M7', score=82.0, className=1}
=======欢迎进入学生成绩管理系统=======
1.新增学生记录
2.修改学生记录
3.删除学生记录
4.按姓名或学号查询学生记录
5.按成绩排序
6.分班级统计
7.退出
请选择(1-7):
4
******************************
请选择按姓名查询还是按照学号查询(1姓名 2学号):2
====查询学生====
请输入要查看的学生学号:
201
查询到该学号记录
StuScore{
no='201', name='M7', score=82.0, className=1}
=======欢迎进入学生成绩管理系统=======
1.新增学生记录
2.修改学生记录
3.删除学生记录
4.按姓名或学号查询学生记录
5.按成绩排序
6.分班级统计
7.退出
请选择(1-7):
5
******************************
按成绩升序显示
学号 班级 姓名 成绩
StuScore{
no='201', name='M7', score=82.0, className=1}
StuScore{
no='202', name='4D', score=82.5, className=2}
StuScore{
no='203', name='A20', score=84.0, className=3}
StuScore{
no='212', name='38tnA', score=86.0, className=2}
=======欢迎进入学生成绩管理系统=======
1.新增学生记录
2.修改学生记录
3.删除学生记录
4.按姓名或学号查询学生记录
5.按成绩排序
6.分班级统计
7.退出
请选择(1-7):
6
******************************
统计(分班级统计学生数量,最高分,最低分,平均值)
一月 19, 2021 4:38:05 下午 com.alibaba.druid.support.logging.JakartaCommonsLoggingImpl info
信息: {
dataSource-1} inited
{
max_score=86.0, count=2, className=2, min_score=82.5, avg_score=84.25}
{
max_score=84.0, count=1, className=3, min_score=84.0, avg_score=84.0}
{
max_score=82.0, count=1, className=1, min_score=82.0, avg_score=82.0}
=======欢迎进入学生成绩管理系统=======
1.新增学生记录
2.修改学生记录
3.删除学生记录
4.按姓名或学号查询学生记录
5.按成绩排序
6.分班级统计
7.退出
请选择(1-7):
7
******************************
您选择了退出系统,确定要退出吗?(y/n)
y
Process finished with exit code -1