数据库课程设计报告
这次的数据库课程设计是基于 JAVA 所设计的一个书店会员管理系统。由于数据库中亦有实体:管理员和工作人员,故此系统可分为3个界面:分别是会员交互系统,工作人员交互系统,以及管理员交互系统。
数据导入
由于数据库中的图书数据匮乏,故写了一个爬虫爬取豆瓣的图书 TOP250,大致如下:
考虑到在交互界面演示时的流畅性,因此只导入前30条的图书数据。导入后的数据库中的表的数据如下:
在导入数据的过程中,使用了 $Functions.batchInputBook()$。
大致代码如下:
public static void batchInputBook() //用一次就够了噢~
{ //对书本的信息进行批量的导入 CSV -------> 数据库
String[][] results = CSVUtil2.CSVProcessing();
for(int i = 0; i <results.length - 1; i++)
{
String book_author = results[i][1];
BigDecimal book_price = new BigDecimal(results[i][2]);
String book_press = results[i][3];
String book_name = results[i][0];
BigDecimal book_quantity = new BigDecimal(500);
insertBookInformation(book_category, book_author, book_price, book_press, book_name, book_quantity);
}
首先通过 $CSVUtil2.CSVProcessing()$ 函数 对目录下的 $douban.csv$ 中的数据进行提取,然后再通过 $Functions$ 中的静态方法 $insertBookInformation()$ 将书的信息插入数据库。
数据属性
考虑到数据库中各个实体的属性可能会存在多次使用的情况,因此将各个属性进行抽象实现。更加方便后续的界面设计。
图书信息
其中,各个变量的意义如下:
- $book_number$:图书编号。
- $book_author$:图书作者。
- $book_category$:图书类别。
- $book_name$:图书名称。
- $book_press$:图书出版社。
- $book_price$:图书价格。
- $book_quantity$:图书库存数量。
会员信息
其中,各个变量的意义如下:
- $member_category$:会员类别。
- $member_gender$:会员编号。
- $member_name$:会员姓名。
- $member_number$:会员编号。
- $member_phone_number$:会员联系方式(特指电话号码)。
购书信息
其中,各个变量的意义如下:
- $purchase_number$:购买记录编号。
- $member_number$:会员编号。
- $purchase_time$:购买时间。
- $member_name$:会员姓名。
- $member_phone_number$:会员联系方式。
- $category_number$:会员类别编号。
- $book_number$:图书编号。
- $book_name$:图书名称。
- $handle$:办理人。
退书信息
其中,各个变量的意义如下:
-
$refund_number$:退书记录编号
- $member_number$:会员编号。
- $refund_time$:退书时间。
- $member_name$:会员姓名。
- $member_phone_number$:会员联系方式。
- $penalty$:罚金。
- $book_number$:图书编号。
- $book_name$:图书名称。
- $handle$:办理人。
员工信息
其中,各个变量的意义如下:
- $staff_number$:员工编号。
- $staff_name$:员工姓名:
- $staff_gender$:员工性别。
- $staff_id_number$:员工身份证号。
- $staff_post$:员工职位。
- $staff_wage$:员工工资。
- $administractor$:管理员。
登录界面设计
登录界面的实现主要在文件 $LogIn.java$ 下。
在其中,将 $username$ (即输入的用户名)和 $password$ (即输入的密码)设置为静态属性。方便其他类(如对数据库进行操作时)进行使用。
验证码的实现见 **其余功能模块 **处。
在登录界面上,用户/员工/管理员可以输入自己的用户名和密码,然后进行登录。
在进行登陆时,会进行多重的判断。
首先会判断用户名和密码是否输入错误,若输入错误,则给出提示。
若用户名和密码输入正确,则会对验证码进行校验。输入错误则提示,输入正确则登录成功。
输入正确;
具体的登录校验过程,在文件 $LoggingVerification.java$ 中实现。
在使用者点击确认登录后,会对文件 $account_information.txt$ 中的数据进行检索。查看是否存在该用户名和密码对,若存在,则登录成功,否则登录失败。
在登录成功之后,会对 druid.properties 中的 username 和 password 进行修改,由于不同的用户属于不同的角色并且具有不同的权限,如此则可以实现不同用户的安全性访问。
验证过程
另外,由于老师对账户是否成功登录持有一丝怀疑态度,接下来将对其登录的成功与否进行验证:
首先,若与数据库连接的用户为 $root$
我们进行一个对图书信息修改的操作,如下:
Functions.modify_book_information("200002", 50.0);
该语句表示,将图书编号为 200002 的图书库存数量增加50;执行结果如下:
执行前:
执行后:
很显然,执行成功。故该函数功能并无错误;由于会员不具有对表的修改权限,接下来通过该函数来对用户是否成功登录进行验证。
将登录的用户改为会员:
由于用户具有对图书表的查询权限,故执行下列语句:
Functions.getBookName();
该函数查询所有的图书名并输入,运行结果如下:
显然,可以正常运行。
接下来执行插入语句的函数。
发生权限错误。故用户成功创建并且具有所分配的会员相应的权限。
很重要的一个语句:
SET global activate_all_roles_on_login=ON;#在MYSQL中所执行
其表示用户连接到服务器时自动激活所有显式授权和强制角色。
注册界面设计
注册界面主要在 $Register.java$ 中实现。
由于为书店会员管理系统,故理所当然,此处的注册按钮仅供用于注册会员账号。
在整个注册的过程中,同样有多重判断。
首先会判断用户名是否与其他会员冲突,若冲突,则通过弹窗提醒。
若上述内容输入正确,则对验证码进行校验。如下:
若输入正确;
此时,在数据库中的会员表中会存入新注册的会员的信息。
同时,会根据其用户米和密码,为其创建一个访问数据库的账户。
可见,注册成功。
会员交互系统设计
会员界面的主要实现在 $user_interface$ 文件夹下。
当输入会员账户密码登入成功后,会进入会员界面。
图书购买
使用的函数包括:
- Functions.purchaseBook()
输入图书名称,即可进行购买。
若输入错误,会弹出弹窗提示,如下:
输入正确;
当购买成功之后,购买记录会添加在第四项:个人的操作记录中,同时也会在数据库中添加响应的数据。
图书退款
使用的函数包括:
- Functions.refundBook()
输入图书名称,即可完成退款。
若该会员并未购买过这本书,则无法完成退款,如下:
输入正确;
当退款操作完成后,退款操作会添加在第四项:个人的操作记录中同时也会在数据库中添加响应的数据。如下:
图书信息查询
使用的函数包括:
- Functions.inquireBookInformationOnBookName(book_name)
当输入正确的书名时,查询成功,并将数据在上面表格进行显示。
若书名不存在库中,弹出弹窗提醒查询失败。
多次查询后,结果如下:
显示个人操作记录
使用的函数包括:
Functions.getMemberPurchaseInformation(username)
Functions.getMemberRefundInformation(username)
当该用户进行购买或退书的操作后,首先对数据库中的表 $purchase_information$ 或 $refund_information$ 进行修改,通过函数 $Functions.purchaseBook()$ 或 $Functions.refundBook()$ 实现,然后根据会员编号对表进行查询。
批量购书
使用的函数包括:
- Functions.purchaseBook()
在这里,会员可以实现勾选复选框来实现批量购买。另外,根据会员的级别不同(1,2,3),图书价格会享受不同的折扣(三级为最高),通过图书价格即可体现。
若会员未勾选方框就进行购买,会弹出弹窗提示操作错误。
操作正确;
在进行批量购书后,同样,也会将这些购买记录显示在第四项:个人的操作记录中,同时,数据库中也会有相应的记录。
书单推荐
书单推荐共有六本书,碍于篇幅限制,在此只展示3本。
可通过上一页,下一页进行翻页查看。
工作人员交互系统设计
图书信息查询
使用到的函数包括:
- Functions.inquireBookInformationOnBookName(book_name)
界面大抵如下,功能与会员界面中的图书信息查询相差无几,不再进行演示。
会员信息查询及修改
使用的函数包括:
Functions.inquireMemberInformationOnMemberNumber1(Integer.valueOf(member_number))。
- Functions.inquireMemberInformationOnMemberName1(member_name)
- Functions.modifyMemberInformation1(member_number, member_name, member_gender, member_phone_number, member_category)
在这个界面中,首先可根据会员的编号对会员信息进行查询。
若输入错误的会员编号,则会提示数据输入错误。
若未输入数据便进行查询,同样会通过弹窗进行提示。
输入正确;
当查询到会员的记录后,可对会员的信息进行修改,如下:
修改后,数据库中的相应数据也会发生变化。
点击清除数据后,即清除掉页面上查询到的所有内容。
购买记录查询
使用的函数包括
$Functions.inquirePurchaseInformationOnPurchaseNumber1(Integer.valueOf(purchase_number))$
$Functions.inquirePurchaseInformationOnMemberNumber1(Integer.valueOf(member_number))$
可根据会员编号进行查询,也可以根据购买记录编号进行查询。
当未输入数据时进行查询,会通过弹窗进行提示。
通过会员编号进行查询:
通过购买记录编号进行查询:
退书记录查询
可根据会员编号进行查询,也可以根据退书记录编号进行查询。
当未输入数据时进行查询,会通过弹窗进行提示。
通过会员编号进行查询:
通过退书记录编号进行查询:
库存补充申请
管理人员可勾选单选框然后填写申请数目补充某个图书的数目,同时在数据库中,会插入该管理人员的库存补充申请记录。
当未勾选任何图书便确认补充,会弹出弹窗提醒操作错误。
同样,若勾选了多个选项,会弹出弹窗提醒申请失败。
操作正确;
此时,数据库中也会多出相应的记录。
后续管理员将可以对申请进行审核,具体见下处 管理员交互系统设计。
管理员交互系统设计
员工信息查询及修改
通过这个界面,可以对员工的信息进行查询和修改。
当未输入数据时,提示错误。
并且,当员工编号输入错误时,通过弹窗提示查询失败。
查询成功;
接下来对员工的信息进行修改。
在数据库中,
会员信息查询及修改
大抵功能与管理员交互系统中的会员信息查询及修改相同,不再进行演示。
图书信息查询(支持信息导出)
在此处可对库中的图书信息进行查询并导出为 .csv 文件。
进行查询时,若未输入任何数据便点击查询,会通过弹窗提示错误。
若输入数据错误,亦会通过弹窗提示错误。
查询成功;
多次查询后,
进行信息导出,会写在文件 output.csv 中。
文件中的内容如下:
图书购买情况
当管理员登陆后,会根据目前销售量最高的前5本书,生成如图所示的饼状图。其中会显示各个书在这5本书当中的销售占比。
另外,会根据该图表在文件夹 generatePicture 中生成相应的 .png 文件并记录有生成的时间(此处的时间为 UNIX 时间戳)。如何管理员则可以通过查看历史记录来进行前后对比,观察某段时间内销量最好的是哪5本书籍。
会员的购买情况
在这个柱状图中,查询了5个会员的购买 8 个书的购买情况。由于图表限制,无法将书名完全显示。由于爬虫爬取的数据可能不太规范,导致部分过长无法显示。
同样,会根据该图表在文件夹 $generatePicture$ 中生成相应的 $.png$ 文件并记录有生成的时间(此处的时间为 $UNIX$ 时间戳)。
补货申请审批
在工作人员提交了补货申请后,管理人员将可以在这里进行审批。
若未勾选任何选项,则会弹出弹窗提示错误。
审批完成;
当审批了一条记录后,数据库中的数据同时也会发生变化。
同时,这个申请记录会被删掉,因为它已经完成了它的工作。
其余功能模块
验证码
验证码的生成分为 $2$ 个文件,分别是 $Code.java$ 和 $CodePicture.java$。
其中 $CodePicture.java$ 用于生成验证码图片,大致流程如下:
// 1.创建空白图片
BufferedImage image = new BufferedImage(
WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
// 2.获取图片画笔
Graphics graphic = image.getGraphics();
// 3.设置画笔颜色
graphic.setColor(Color.LIGHT_GRAY);
// 4.绘制矩形背景
graphic.fillRect(0, 0, WIDTH, HEIGHT);
// 5.画随机字符
Random ran = new Random();
for (int i = 0; i < SIZE; i++) {
// 取随机字符索引
int n = ran.nextInt(chars.length);
// 设置随机颜色
graphic.setColor(getRandomColor());
// 设置字体大小
graphic.setFont(new Font(
null, Font.BOLD + Font.ITALIC, FONT_SIZE));
// 画字符
graphic.drawString(
chars[n] + "", i * WIDTH / SIZE, HEIGHT / 2 + 10);
// 记录字符
sb.append(chars[n]);
}
// 6.画干扰线
for (int i = 0; i < LINES; i++) {
// 设置随机颜色
graphic.setColor(getRandomColor());
// 随机画线
graphic.drawLine(ran.nextInt(WIDTH), ran.nextInt(HEIGHT),
ran.nextInt(WIDTH), ran.nextInt(HEIGHT));
}
// 7.返回验证码和图片
return new Object[]{sb.toString(), image};
$Code.java$ 主要用于设置验证码图片位置及设置相关事件触发。
对象创建及大小设置:
JLabel code = new JLabel();
Object[] obj = CodePicture.createImage();
ImageIcon img = new ImageIcon((BufferedImage)obj[1]);//创建图片对象
code.setIcon((Icon)img);
code.setBounds(450, 290,150, 50);
panel.add(code);
鼠标点击监听:
change.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e){
if(e.getClickCount() == 1){
//重新获取验证码
Object[] obj1 = CodePicture.createImage(); //再次生成对象。
ImageIcon img1 = new ImageIcon((BufferedImage)obj1[1]);//创建图片对象
code.setIcon((Icon)img1);
code.setBounds(450, 290,150, 50);
panel.add(code);
}
}
});
背景音乐
由于无法演示,故将其挪至其余功能模块。
背景音乐的播放主要通过模块 $javax.sound.sampled$ 实现。
需要带有的功能有:
- 获取数据(音频中的)
- 播放音频。
- 暂停播放音频。
- 继续播放音频。
- 生成音频主线程。
- 暂停音频线程。
- 继续音频线程。
表格风格修改
由于当个修改表格的字体、间隔等过于麻烦,故通过一个函数进行统一处理。
若想修改某个表格的风格,则使用 $TableStyle.setTableStyle()$ 即可。
在这个文件中,主要对表格做了如下的修改:
- 表头自动排序。
- 标头的文字居中显示。
- 字体的调整。
- 根据内容对表格的列宽度进行调整。
- 设置表格每行的高度。
修改配置文件
在 ModifyDruidProperties.java 中实现对配置文件的修改,以达到切换用户连接数据库的目的。
实现则是简简单单的文件操作,不再进行阐释。
注:在每次一个用户登录后,对$username$,$password$,分别进行修改。在用户退出后,把 $username$,$password$,修改回 $root$。另,此处的退出需手动叉掉用户界面然后在通过按钮来停掉主程序,否则可能会出现无法写回 $root$ 用户名密码的情况。
数据库连接
主要在 $JDBCUtil.java$ 下进行实现。
首先通过 $Properties$ 来获取 $URL$,$DRIVER$,$PASSWORD$等;
其次再使用 $Druid$ 连接池进行连接。
使用 $Druid$ 进行连接有如下的好处:
- 可以有效地避免 $sql$ 注入问题。
- $Druid$ 提供了一个高效、功能强大、可扩展性好的数据库连接池,并有效的替换了 $DBCP$ 和 $C3P0$。
- 可以对数据库的访问性能进行监控,基于其中的一个叫 $StatFilter$ 的插件。
- 可以实现对 $JDBC$ 层的扩展。