一、项目概述
图书馆是一个提供书籍、资料等学习资源的场所,对于学生、教师等用户来说具有重要意义。本系统的目标是为图书馆提供一套高效、便捷的信息管理系统,提供图书管理功能、读者管理功能、借阅统计功能、管理员服务质量评定等功能。
注意:MySQL版本为8、jdk8
二、需求分析
数据字典:
1.读者信息数据
(1)数据项1{
数据项名:卡号
描述:唯一标识一位读者,长度为7,前两位是年级编号,第3、4位是专业编号,后三位按顺序编号
类型:字符串
取值范围:“0000000”~ “9999999”
}
(2)数据项2{
数据项名:姓名
描述:对读者的一种标识,但不唯一 ,长度在2-20个字符之间的字符串,不可以为空
类型:字符串
取值范围:由汉字和字母组成的字符串
}
. (3)数据项3{
数据项名:性别
描述:用来区别读者的性别,长度为3,不可以为空
类型:字符串
取值范围:男、女
}
(4)数据项4{
数据项名:职务
描述:可以用来知道读者是老师还是学生等身份,长度为10,不可以为空
类型:字符串
取值范围:学校中所具有的职务均可
}
(5)数据项5{
数据项名:罚款金额
描述:不同的损坏程度对应不同的罚款额,损坏程度由高到低依次罚款20、10、0,不可以为空
类型:整型
取值范围:仅能取20、10或0
}
2.图书信息数据
(1)数据项1{
数据项名:书号
描述:可用来唯一标识书本,长度为7
类型:字符串
取值范围:“0000000”~“9999999”
}
(2)数据项2{
数据项名:书名
描述:读者可以通过书名来查寻自己想要借阅的图书,长度为1~30的字符串,不能为空
类型:字符串
取值范围:由汉字和字母组成
}
(3)数据项3{
数据项名:作者
描述:图书创作人的姓名,不能为空,长度为1~20的字符串
类型:字符串
取值范围:由汉字和字母组成
}
(4)数据项4{
数据项名:存放位置
描述:可以表示出在图书在哪个书架、第几层,例“101-3”,表示在101号书架,第3层,便于寻找,长度为4
类型:字符串
取值:“001-1”至“999-9”
}
3.书架信息数据
(1)数据项1{
数据项名:书架编号
描述:用来唯一标识一个书架,长度为3
类型:字符串
取值范围:“001”~“999”
}
(2)数据项2{
数据项名:状态
描述:用来表示书架此时的状态,不能为空,长度为6
类型:字符串
取值范围:{存满、有书、空}
}
4.管理员信息数据
(1)数据项1{
数据项名:工作号
描述:可以唯一标识一位管理员
类型:字符串
取值范围:“0”~ “9”
}
(2)数据项2{
数据项名:姓名
描述:由字母和汉字组成,可以用来区别管理员,但不唯一,长度为1~20不能为空
类型:字符
取值范围:由汉字和字母组成
}
(3)数据项3{
数据项名:年龄
描述:用来表示管理员的年纪大小,长度为3
类型:字符串
取值范围: “000”~“130”
}
5.供应商信息数据
(1)数据项1{
数据项名:供应商名
描述:唯一标识一家供应商,某图书对应的供应商名,相同类型书可对应不同的供应商,同一供应商可对应多种图书,长度为2~20
类型:字符串
取值范围:由汉字和字母组成
}
(2)数据项2{
数据项名:地址
描述:记录供应商的地理位置,长度为2~50,不能为空
类型:字符串
取值范围:由汉字、字母、数字组成
}
(3)数据项3{
数据项名:联系电话
描述:电话号码的数字一共有11位,前3位代表网络识别号,第4-7位代表地区编码,第8-11位代表用户号码(随机分配的)
类型:字符串
}
6、罚款评定信息数据
(1)数据项1{
数据项名:损坏程度
描述:用特定的词语描述读者对书本造成的损坏程度,长度为6
类型:字符串
取值范围:严重、轻微、无(没有损坏)
}
(2)数据项2{
数据项名:罚款金额
描述:不同的损坏程度对应不同的罚款额,损坏程度由高到低依次罚款20、10、5
类型:整型
取值范围:仅能取20、10或5
}
三、概念结构设计
(一)实体及联系的定义
读者(卡号,姓名,性别,职务,罚款)。
图书(书号,书名,作者,存放位置)
供应商(供应商名称,地址,电话)
管理员(工作号,姓名,年龄)
书架(书架编号,状态)
罚款评定(损坏程度,罚款金额)
借阅归还记录(卡号, 书号, 借阅时间、归还时间)
图书供应(供应商名,书号, 运输方式)
服务(工作号,卡号,管理员,读者, 评分)
逾期(卡号, 书号, 逾期天数)
破损(卡号,书号,破损情况)
(二)实体图及实体联系E-R图
四、逻辑结构设计
Reader(Rno, Rname, Rsex, Rjob, Rfine,Drank)
Book(Bno, Bname, Bwriter, Bplace)
Provider(Pname, Paddr, Ptele)
Manager(Mno, Mname, Mage)
Shelf(Sno,Sstate)
Damage(Drank, Dfine)
BorrowReturenRecord(Rno, Bno, Borr_time, Ret_time)
BP(Pname,Bname,transport)
Service(Mno, Rno, grade)
Overdue(Rno, Bno, days)
Break(Rno,Bno,degree)
五、物理结构的设计及实施
(一)创建数据库
(二)创建表及约束条件
-- 创建读者表
CREATE TABLE Reader(
Rno varchar(7) PRIMARY KEY,
Rname VARCHAR(20) NOT NULL,
Rsex CHAR(3) CHECK(Rsex IN ("男","女")),
Rjob VARCHAR(10) NOT NULL,
Drank VARCHAR(8);
Dfine INT CHECK(Dfine = 20 OR Dfine = 10 OR Dfine = 0)
);
-- 创建图书表
CREATE TABLE Book(
Bno VARCHAR(7) PRIMARY KEY,
Bname varchar(30) NOT NULL,
Bwriter VARCHAR(20) NOT NULL,
Bplace VARCHAR(6) NOT NULL
);
-- 创建供应商表
CREATE TABLE Provider(
Pname varchar(20) PRIMARY KEY,
Paddr varchar(50) NOT NULL,
Ptele varchar(11) NOT NULL
);
-- 创建管理员表
CREATE TABLE Manager(
Mno char PRIMARY KEY,
Mname varchar(20) NOT NULL,
Mage int
);
-- 创建书架信息表
CREATE TABLE Shelf(
Sno VARCHAR(3) PRIMARY KEY,
SState VARCHAR(6) NOT NULL
);
-- 创建损坏评定标准表
CREATE TABLE Damage(
Drank VARCHAR(8) PRIMARY KEY,
Dfine INT CHECK(Dfine = 20 OR Dfine = 10 OR Dfine = 0)
);
-- 创建借阅记录表
CREATE TABLE BorrowReturnRecord(
Rno varchar(7),
Bno VARCHAR(7) ,
BRtime DATE NOT NULL,
Ret_time DATE NOT NULL,
CONSTRAINT k1 PRIMARY KEY(Rno, Bno),
CONSTRAINT fk_Re_BRR FOREIGN KEY(Rno) REFERENCES Reader(Rno),
CONSTRAINT fk_Bo_BRR FOREIGN KEY(Bno) REFERENCES Book(Bno)
);
-- 创建供应商与图书之间的供应关系表
CREATE TABLE BP(
Pname VARCHAR(20),
Bno VARCHAR(7),
transport varchar(15),
count Int,
CONSTRAINT k4 PRIMARY KEY(Pname, Bno),
CONSTRAINT fk_Pr_BP FOREIGN KEY(Pname) REFERENCES Provider(Pname),
CONSTRAINT fk_Pr_Bo FOREIGN KEY(Bno) REFERENCES book(Bno)
);
-- 创建管理员与读者之间的服务信息表
CREATE TABLE Service(
Mno CHAR,
Rno VARCHAR(7),
grade INT,
CONSTRAINT k5 PRIMARY KEY(Mno,Rno),
CONSTRAINT fk_Re_S FOREIGN KEY(Rno) REFERENCES Reader(Rno),
CONSTRAINT fk_Ma_S FOREIGN KEY(Mno) REFERENCES Manager(Mno)
);
-- 创建逾期表
CREATE TABLE overdue(
Rno varchar(7),
Bno VARCHAR(7),
days int,
CONSTRAINT k6 PRIMARY KEY(Rno, Bno),
CONSTRAINT fk_Re_ov FOREIGN KEY(Rno) REFERENCES reader(Rno),
CONSTRAINT fk_Bo_ov FOREIGN KEY(Bno) REFERENCES book(Bno)
);
-- 创建读者的损坏记录
CREATE TABLE break(
Rno varchar(7),
Bno VARCHAR(7),
degree VARCHAR(8),
CONSTRAINT k7 PRIMARY KEY(Rno, Bno),
CONSTRAINT fk_Re_br FOREIGN KEY(Rno) REFERENCES reader(Rno),
CONSTRAINT fk_Bo_br FOREIGN KEY(Bno) REFERENCES book(Bno)
);
-- 创建的存储过程:
CREATE PROCEDURE getLevel(
IN inMno VARCHAR(1),
OUT outlevel INT)
BEGIN
DECLARE totallevel INT;
DECLARE grade INT;
DECLARE templevel FLOAT;
DECLARE num INT;
DECLARE v_done INT DEFAULT 0;
DECLARE mycursor CURSOR FOR
SELECT s.grade FROM service s
JOIN manager m ON s.Mno = m.Mno
WHERE s.Mno = inMno;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_done := TRUE;
SET totallevel :=0;
SET num := 0;
OPEN mycursor;
myloop: LOOP
FETCH mycursor INTO grade;
IF v_done THEN
LEAVE myloop;
END IF;
IF grade BETWEEN 90 AND 100 THEN SET templevel := 10.0;
ELSEIF grade BETWEEN 80 AND 89 THEN SET templevel := 8.0;
ELSEIF grade BETWEEN 70 AND 79 THEN SET templevel := 7.0;
ELSEIF grade BETWEEN 60 AND 69 THEN SET templevel := 6.0;
ELSE SET templevel := 5.0;
END IF;
SET totallevel := totallevel+templevel;
SET num := num + 1;
END LOOP;
CLOSE mycursor;
SET outlevel := totallevel / num;
END;
(三)创建索引
CREATE INDEX idx_service ON service(rno,mno);
CREATE INDEX idx_reader ON reader(rno, rname);
CREATE INDEX idx_book on book(bno, bname);
(四)加载数据
INSERT INTO Reader
VALUES
("2284167","李明","男","学生","无",0),
("2284002","小红","女","学生","严重",20),
("2284321","张三","男","教师","无",0),
("2284164","王丽","女","学生","轻微",10),
("2284187","杨刚","男","学生","无",0);
INSERT INTO Book
VALUES
("1100023","理想国","柏拉图","101-3"),
("2254130","老人与海","海明威","102-2"),
("0021365","物理学","李帅朋","103-6"),
("5521301","活着","老舍","201-1"),
("0214536","简爱","李白","106-2"),
("0215478","论语","孔子","205-6");
INSERT INTO Provider
VALUES
("滕训公司","河南","18303636327"),
("亿动公司","上海","15362486521"),
("平裹公司","北京","10324561598");
INSERT INTO Manager
VALUES
("1","小帅帅","18"),
("2","小诗诗","19"),
("3","小文文","32");
INSERT INTO Shelf
VALUES
("101","有书"),
("102","有书"),
("103","有书"),
("201","有书"),
("106","有书"),
("205","有书");
INSERT INTO Damage
VALUES
("严重",20),
("轻微",10),
("无",0);
INSERT INTO BorrowReturnRecord
VALUES
("2284002","1100023","2023-01-02","2023-04-01"),
("2284167","0215478","2023-12-27","2024-01-02"),
("2284002","0021365","2023-03-01","2023-04-11"),
("2284002","0214536","2023-06-03","2023-06-08"),
("2284321","0021365","2022-04-05","2022-09-01"),
("2284164","0214536","2021-03-04","2021-05-14"),
("2284187","0021365","2023-02-08","2023-11-18"),
("2284187","0214536","2022-11-26","2022-12-20");
INSERT INTO BP
VALUES
("滕训公司","2254130","铁路",2),
("亿动公司","0215478","空运",3),
("平裹公司","0021365","水路",4),
("滕训公司","5521301","空运",1),
("亿动公司","1100023","铁路",5),
("平裹公司","0214536","水路",2),
("滕训公司","0215478","空运",100),
("亿动公司","0021365","水路",50),
("平裹公司","2254130","铁路",40);
INSERT INTO overdue
VALUES
("2284167","1100023",2),
("2284321","0215478",3);
INSERT INTO break
VALUES
("2284167","1100023","无"),
("2284321","0215478","轻微");
INSERT INTO Service
VALUES
('1',"2284167","95"),
("3","2284167","91"),
("1","2284002","92"),
("3","2284321","96"),
("1","2284321","91"),
("3","2284164","92"),
("2","2284164","91"),
("3","2284187","99"),
("2","2284167","94");
六、系统实现
要求:
采用JDBC连接数据方式操作数据库
采用简单控制台操作界面实现数据库的增删改查操作
至少实现5种以上的菜单功能,其中要有一个复杂的业务加工逻辑有存储过程实现。
public class Main {
public static void main(String[] args) throws SQLException {
Scanner sc = new Scanner(System.in);
while (true){
printMenu();
System.out.print("请输入你的需求:");
int choice = sc.nextInt();
switch (choice){
case 0:
System.exit(0);
break;
case 1:
ReaderAdd readerAdd = new ReaderAdd();//添加读者信息
readerAdd.add();
break;
case 2:
ReaderDelete readerDelete = new ReaderDelete();
readerDelete.delete();//删除读者信息
break;
case 3:
BookCount bookCount = new BookCount();
bookCount.getBookCount();//统计图书的数目
break;
case 4:
ProviderModify providerModify = new ProviderModify();
providerModify.modify();//修改供应商的信息
break;
case 5:
BookDetail bookDetail = new BookDetail();
bookDetail.getBookDetail();//查询图书列表
break;
case 6:
ServiceQuality serviceQuality = new ServiceQuality();
serviceQuality.getServiceQuality();//输入管理员工作号查询他(她)的服务质量等级,最高为10.0,
break; //该功能使用存储过程
default:
System.out.println("选择错误,请重新选择");
}
}
}
public static void printMenu(){
System.out.println("=========欢迎来到图书管理系统=========");
System.out.println("0.退出");
System.out.println("1.添加读者信息");
System.out.println("2.删除读者信息");
System.out.println("3.统计图书的册数");
System.out.println("4.修改供应商信息");
System.out.println("5.查看图书表");
System.out.println("6.管理员服务质量评定");
}
}
获取connection:
public class DatabaseConnection {
public static Connection conn(){
Connection connection;
String url = "jdbc:mysql://localhost:3306/librarysys?serverTimezone=GMT%2B8"; //数据库连接的url地址
String user = "root"; //数据库用户名
String password = "1127"; //数据库密码
try {
//加载数据库驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//System.out.println("数据库驱动加载成功!");
}catch (ClassNotFoundException e) {
e.printStackTrace();
}
try{
//通过DriverManager获取数据库连接
connection = DriverManager.getConnection(url,user,password);
//System.out.println("数据库连接成功!");
return connection;
}catch (SQLException e) {
e.printStackTrace();
return null;
}
}
}
添加读者信息:
public class ReaderAdd {
public void add() throws SQLException {
Connection conn = DatabaseConnection.conn();
Statement statement = conn.createStatement();
Scanner sc = new Scanner(System.in);
System.out.println("请输入卡号、姓名、性别、职位和罚款金额:");
String no = sc.next();
String name = sc.next();
String sex = sc.next();
String job = sc.next();
int fine = sc.nextInt();
String sql = "INSERT INTO Reader VALUES('"+no+"','"+name+"','"+sex+"','"+job+"',"+fine+")";
statement.executeUpdate(sql);
System.out.println("添加成功!");
conn.close();
statement.close();
}
}
删除读者信息:
public class ReaderDelete {
public void delete() throws SQLException {
Connection conn = DatabaseConnection.conn();
Statement statement = conn.createStatement();
Scanner sc = new Scanner(System.in);
System.out.println("请输入要删除的读者的图书卡号:");
String Rno = sc.next();
String sql = "delete from Reader where Rno = '"+Rno+"'";
int count = statement.executeUpdate(sql);
if(count != 0)
System.out.println("删除成功!");
else
System.out.println("删除失败!");
}
}
统计图书的数量:
public class BookCount {
public void getBookCount() throws SQLException {
Connection conn = DatabaseConnection.conn();
Statement statement = conn.createStatement();
String sql = "select COUNT(*) as num from Book";
ResultSet resultSet = statement.executeQuery(sql);
while(resultSet.next()){
int num = resultSet.getInt("num");
System.out.println("图书馆中共藏书:"+num+"本");
}
conn.close();
statement.close();
}
}
修改供应商信息:
public class ProviderModify {
public void modify() throws SQLException {
Connection conn = DatabaseConnection.conn();
Statement statement = conn.createStatement();
Scanner sc = new Scanner(System.in);
System.out.print("请输入供应商名称:");
String Pname = sc.next();
System.out.println("==========");
System.out.println("1.地址");
System.out.println("2.电话");
System.out.println("3.地址、电话");
System.out.println("请选择要修改的内容:");
int choice = sc.nextInt();
switch (choice){
case 1:
System.out.println("请输入地址:");
String addr = sc.next();
String sql = "UPDATE Provider "+
"set Paddr = '"+addr+
"'where Pname='"+Pname+"'";
statement.executeUpdate(sql);
break;
case 2:
System.out.println("请输入电话:");
String tele = sc.next();
String sql2 = "UPDATE Provider "+
"set Ptele ='"+tele+
"'where Pname='"+Pname+"'";
statement.executeUpdate(sql2);
break;
case 3:
System.out.println("请输入地址、电话:");
String addr1 = sc.next();
String tele1 = sc.next();
String sql3 = "UPDATE Provider "+
"set Paddr='"+addr1+"',Ptele ='"+tele1+
"' where Pname='"+Pname+"'";
statement.executeUpdate(sql3);
break;
default:
System.out.println("选择错误请重新选择。");
break;
}
System.out.println("修改成功!");
conn.close();
statement.close();
}
}
查看图书信息:
public class BookDetail {
public void getBookDetail() throws SQLException {
Connection conn = DatabaseConnection.conn();
Statement statement = conn.createStatement();
String sql = "select * from Book";
ResultSet rs = statement.executeQuery(sql);
System.out.println("书号 || 书名 || 作者 || 位置 ");
while(rs.next()){
String Bno = rs.getString("Bno");
String Bname = rs.getString("Bname");
String Bwriter = rs.getString("Bwriter");
String Bplace = rs.getString("Bplace");
System.out.println(Bno+"\t《"+Bname+"》\t"+Bwriter+"\t"+Bplace);
}
conn.close();
statement.close();
}
}
管理员服务质量评定,管理员服务评定功能是通过存储过程实现的复杂业务逻辑(存储过程代码粘贴在上面):
public class ServiceQuality {
public void getServiceQuality() throws SQLException {
Connection conn = DatabaseConnection.conn();
CallableStatement stmt = conn.prepareCall("{CALL getLevel(?,?)}");
Scanner sc = new Scanner(System.in);
System.out.println("请输入你要评定服务等级的管理员的工作号:");
String inMno = sc.next();
stmt.setString(1,inMno);
stmt.registerOutParameter(2, Types.REAL);
stmt.execute();
float outLevel = stmt.getFloat(2);
System.out.println("该管理员的服务质量等级为:"+outLevel);
conn.close();
stmt.close();
}
}