这是这个学期Java实训课的课程设计,实训的主要内容的JDBC连接操纵数据库,选取驾考试题管理作为项目命题,总的来说这个项目很简单,就是最基本的增删查改。同样的这次也是选用JavaFx做UI端,感觉虽然JavaFx没有MFC那样所见即所得,但自己也摸索了一些形式,配合支持FXML的JavaFX Scene Builder ,再加上点CSS,感觉像是在做网页?博客大部分内容直接摘自实训报告吧,当时为了凑字数,啰里啰嗦说了一堆废话,凑合看吧。
一、系统描述
随着我国社会的不断进步和发展,越来越多的家庭拥有汽车,人们把驾驶汽车作为外出游玩,上下班的第一选择,因而大众对驾驶技能考试的热情越来越高涨,开发本系统的主要目的是为了给准备驾驶技能考试科目一、科目四的考生构建一个能够进行增删查改的数据库。由于科目一和科目四只有单选题和判断题,因而本数据库只需要根据单选题和判断题的特征,抽象出两张表即可。
本驾考试题管理系统是一个管理试题资源的工具软件,采用模块化思想,基于Windows环境和Java平台提供的Derby数据库,使用IDEA软件作为开发环境,系统包括单选题管理和判断题管理两大功能模块,每个大模块下又包含添加试题、更新试题、删除试题和查询试题这四个子模块。这样的模块化结构一方面可以减少各个模块之间的依赖,降低系统开发的复杂度;另一方面也便于之后系统的维护和功能升级。
二、总体结构
1、系统结构设计
2、数据库结构设计
本系统设计了2个表,抽象为两个对象,绘制E-R图。
ChoiceQuestion表:
用于记录选择题信息和答案
Number:题目编号
Content:题目内容
Pic:图片名称
Answer:正确答案
optionA:选项A
optionB:选项B
optionC:选项C
optionD:选项D
TFQuestion表:
用于记录判断题信息和答案
Number:题目编号
Content:题目内容
Pic:图片名称
Answer:正确答案
optionT:选项1
optionF:选项2
SQL建表语句如下:
create table ChoiceQuestion
(number char(10) primary key,content varchar(100),pic varchar(50),optionA varchar(50),optionB varchar(50),optionC varchar(50),optionD varchar(50),answer char(2) );
create table TFQuestion
(number char(10) primary key,content varchar(100),pic varchar(50),optionA char(6) default '正确',optionB char(6) default '错误',answer char(2) );
三、功能描述
(1)用户根据单选题的格式,依照相应的规范进行单选题的增添、修改、删除和查询,输入信息不规范会有信息提示窗口。
(2)用户根据查询子模块的查询功能,依照查询得到题目记录,有选择地进行修改和删除。
实现原理
用户在前端JavaFX界面上输入信息,触发事件处理,将输入的数据传输到业务层,通过DAO模式,对Derby数据库进行增删查改。而进行数据库操作的关键是JDBC,可以为多种关系型数据库DBMS提供统一的访问方式,主要目的是用Java来操作数据库。
JDBC API主要负责三个功能:(1)与数据库建立连接(2)发送SQL语句给数据库(3)数据库将结果返回
四、相关类的实现
这里主要介绍选择题和判断题的两个实体类ChoiceQuestion、TrueFalseQuestion还有对应的两个数据库操作DAO类ChoiceQuestionDao、TFQuestionDao,以及封装好的数据库配置类DBUtils。
ChoiceQuestion类
package pojo; public class ChoiceQuestion { String number;//题目编号 String content;//题目内容 String pic;//图片名称 String optionA;//选项 String optionB; String optionC; String optionD; String answer;//正确答案 public ChoiceQuestion(String number, String content, String pic, String optionA, String optionB, String optionC, String optionD, String answer) { this.number = number; this.content = content; this.pic = pic; this.optionA = optionA; this.optionB = optionB; this.optionC = optionC; this.optionD = optionD; this.answer = answer; } public ChoiceQuestion() { } public String getNumber() { return number; } public void setNumber(String number) { this.number = number; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String getPic() { return pic; } public void setPic(String pic) { this.pic = pic; } public String getOptionA() { return optionA; } public void setOptionA(String optionA) { this.optionA = optionA; } public String getOptionB() { return optionB; } public void setOptionB(String optionB) { this.optionB = optionB; } public String getOptionC() { return optionC; } public void setOptionC(String optionC) { this.optionC = optionC; } public String getOptionD() { return optionD; } public void setOptionD(String optionD) { this.optionD = optionD; } public String getAnswer() { return answer; } public void setAnswer(String answer) { this.answer = answer; } @Override public String toString() { return "ChoiceQuestion{" + "number='" + number + '\'' + ", content='" + content + '\'' + ", pic='" + pic + '\'' + ", optionA='" + optionA + '\'' + ", optionB='" + optionB + '\'' + ", optionC='" + optionC + '\'' + ", optionD='" + optionD + '\'' + ", answer='" + answer + '\'' + '}'; } }
TrueFalseQuestion类
package pojo; public class TrueFalseQuestion { String number;//题目编号 String content;//题目内容 String pic;//图片名称 String optionT;//选项 String optionF; String answer;//正确答案 public TrueFalseQuestion(String number, String content, String pic, String optionT, String optionF, String answer) { this.number = number; this.content = content; this.pic = pic; this.optionT = optionT; this.optionF = optionF; this.answer = answer; } public TrueFalseQuestion() { } public String getNumber() { return number; } public void setNumber(String number) { this.number = number; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String getPic() { return pic; } public void setPic(String pic) { this.pic = pic; } public String getOptionT() { return optionT; } public void setOptionT(String optionT) { this.optionT = optionT; } public String getOptionF() { return optionF; } public void setOptionF(String optionF) { this.optionF = optionF; } public String getAnswer() { return answer; } public void setAnswer(String answer) { this.answer = answer; } @Override public String toString() { return "TrueFalseQuestion{" + "number='" + number + '\'' + ", content='" + content + '\'' + ", pic='" + pic + '\'' + ", optionT='" + optionT + '\'' + ", optionF='" + optionF + '\'' + ", answer='" + answer + '\'' + '}'; } }
ChoiceQuestionDao类
package dao; import pojo.ChoiceQuestion; import util.DBUtils; import java.sql.*; import java.util.ArrayList; public class ChoiceQuestionDao { private static Connection connection = DBUtils.getConnection(); public static boolean ChoiceItemInsert(ChoiceQuestion cq) { PreparedStatement preparedStatement; String sql = "insert into ChoiceQuestion(number,content,pic,optionA,optionB,optionC,optionD,answer) values(?,?,?,?,?,?,?,?)"; try { if (cq != null) { preparedStatement = connection.prepareStatement(sql); preparedStatement.setString(1, cq.getNumber()); preparedStatement.setString(2, cq.getContent()); preparedStatement.setString(3, cq.getPic()); preparedStatement.setString(4, cq.getOptionA()); preparedStatement.setString(5, cq.getOptionB()); preparedStatement.setString(6, cq.getOptionC()); preparedStatement.setString(7, cq.getOptionD()); preparedStatement.setString(8, cq.getAnswer()); //修改表中的内容executeUpdate返回值是一个整数 return preparedStatement.executeUpdate() > 0; } } catch (SQLException e) { e.printStackTrace(); } return false; } public static boolean ChoiceItemDelete(String number) throws SQLException { PreparedStatement preparedStatement; String sql = "delete from ChoiceQuestion where number = ?"; PreparedStatement pst = connection.prepareStatement(sql); pst.setString(1,number); int result = pst.executeUpdate();//返回值表示受到影响的行数 if(result>0) { return true; } return false; } //单个具体查找,根据题目编号 public static ChoiceQuestion ChoiceItemQuerySingle(String number) throws SQLException { String sql = "select * from ChoiceQuestion where number = ?"; //要执行的SQL PreparedStatement pst = connection.prepareStatement(sql); pst.setString(1,number); ResultSet rs = pst.executeQuery();//创建数据对象,注意预定义语句上允许带参数 ChoiceQuestion cq = new ChoiceQuestion(); while (rs.next()){ cq.setNumber(rs.getString(1)); cq.setContent(rs.getString(2)); cq.setPic(rs.getString(3)); cq.setOptionA(rs.getString(4)); cq.setOptionB(rs.getString(5)); cq.setOptionC(rs.getString(6)); cq.setOptionD(rs.getString(7)); cq.setAnswer(rs.getString(8)); System.out.println(cq.toString()); } return cq;//返回查找到的单选题目 } public static ArrayListChoiceItemQuery() { String sql = "select * from ChoiceQuestion"; //要执行的SQL ArrayList acq=new ArrayList(); try { Statement stmt = connection.createStatement(); //创建Statement对象 ResultSet rs = stmt.executeQuery(sql);//创建数据对象 while (rs.next()){ ChoiceQuestion cq = new ChoiceQuestion(); cq.setNumber(rs.getString(1)); cq.setContent(rs.getString(2)); cq.setPic(rs.getString(3)); cq.setOptionA(rs.getString(4)); cq.setOptionB(rs.getString(5)); cq.setOptionC(rs.getString(6)); cq.setOptionD(rs.getString(7)); cq.setAnswer(rs.getString(8)); acq.add(cq); System.out.println(cq.toString()); } } catch (SQLException e) { e.printStackTrace(); } return acq;//返回ArrayList } }
TFQuestionDao类
package dao; import pojo.TrueFalseQuestion; import util.DBUtils; import java.sql.*; import java.util.ArrayList; public class TFQuestionDao { private static Connection connection = DBUtils.getConnection(); public static boolean TFItemInsert(TrueFalseQuestion tfq) { System.out.println(tfq.toString()); PreparedStatement preparedStatement; String sql = "insert into TFQuestion(number,content,pic,optionA,optionB,answer) values(?,?,?,?,?,?)"; try { if (tfq != null) { preparedStatement = connection.prepareStatement(sql); preparedStatement.setString(1, tfq.getNumber()); preparedStatement.setString(2, tfq.getContent()); preparedStatement.setString(3, tfq.getPic()); preparedStatement.setString(4, tfq.getOptionT()); preparedStatement.setString(5, tfq.getOptionF()); preparedStatement.setString(6, tfq.getAnswer()); //修改表中的内容executeUpdate返回值是一个整数 return preparedStatement.executeUpdate() > 0; } } catch (SQLException e) { e.printStackTrace(); } return false; } public static boolean TFItemDelete(String number) throws SQLException { PreparedStatement preparedStatement; String sql = "delete from TFQuestion where number = ?"; PreparedStatement pst = connection.prepareStatement(sql); pst.setString(1,number); int result = pst.executeUpdate();//返回值表示受到影响的行数 if(result>0) { return true; } return false; } //单个具体查找,根据题目编号 public static TrueFalseQuestion TFItemQuerySingle(String number) throws SQLException { String sql = "select * from TFQuestion where number = ?"; //要执行的SQL PreparedStatement pst = connection.prepareStatement(sql); pst.setString(1,number); ResultSet rs = pst.executeQuery();//创建数据对象,注意预定义语句上允许带参数 TrueFalseQuestion tfq = new TrueFalseQuestion(); while (rs.next()){ tfq.setNumber(rs.getString(1)); tfq.setContent(rs.getString(2)); tfq.setPic(rs.getString(3)); tfq.setOptionT(rs.getString(4)); tfq.setOptionF(rs.getString(5)); tfq.setAnswer(rs.getString(6)); System.out.println(tfq.toString()); } return tfq;//返回查找到的单选题目 } public static ArrayListTFItemQuery() { String sql = "select * from TFQuestion"; //要执行的SQL ArrayList atfq=new ArrayList(); try { Statement stmt = connection.createStatement(); //创建Statement对象 ResultSet rs = stmt.executeQuery(sql);//创建数据对象 while (rs.next()){ TrueFalseQuestion tfq = new TrueFalseQuestion(); tfq.setNumber(rs.getString(1)); tfq.setContent(rs.getString(2)); tfq.setPic(rs.getString(3)); tfq.setOptionT(rs.getString(4)); tfq.setOptionF(rs.getString(5)); tfq.setAnswer(rs.getString(6)); atfq.add(tfq); System.out.println(tfq.toString()); } } catch (SQLException e) { e.printStackTrace(); } return atfq;//返回ArrayList } }
DBUtils类
package util; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; //数据库工具类 public class DBUtils { private static Connection connection; private static String dirverName = "org.apache.derby.jdbc.EmbeddedDriver"; private static String uri = "jdbc:derby:MyDB/DrivingTest;create=true"; //这里将Derby数据库创建到本项目的目录下 //加载数据 库驱动 public DBUtils() { super(); try { Class.forName(dirverName); } catch (Exception e) { System.out.print("数据库驱动加载异常" + e); } } //获取数据库连接对象 public static Connection getConnection() { try { if (connection == null) { connection = DriverManager.getConnection(uri);//Derby数据库建立连接 } } catch (SQLException e) { System.out.println("连接数据库异常" + e); } return connection; } }
五、界面设计
本系统的图形界面使用JavaFX开发,可以使用FXML编写,该语言是基于XML的标记语言,用于定义用户界面,容易开发与维护。可以通过使用层叠样式表CSS,轻松定制。
本项目的面板结构
单选题管理界面
单选题添加界面:
单选题更新界面:
单选题删除界面:
单选题查询界面:
判断题管理界面
判断题添加界面:
判断题更新界面:
判断题删除界面:
判断题查询界面:
六、程序设计
该系统的项目程序代码在伴随本文档的压缩包中给出,本系统开发环境为Windows10,开发软件为idea,并在eclipse下测试通过。这个给出描述本程序的文件目录树结构。
其中MyDB下的DrivingTest为本项目的Derby数据库,本项目主要位于src目录下,其中pojo下的ChoiceQuestion和TrueFalseQuestion为单选题和判断题的两个试题类;dao包下是用于单选题和判断题用于数据库操作的类;sample包用于生成图形界面和事物处理;util包下的DBUtils用于数据库驱动配置等。
七、总结
本次Java实训课的主要内容是通过JDBC来操作数据库,完成一个简单的驾考试题管理系统,了解了Apache Derby这样一个与平台无关的Java数据库,学会了两种操作Derby数据库的方式,通过本地连接和网络连接。之后通过一系列基础的查询操作、更新操作、添加和删除操作,基本掌握了JDBC操作数据库的流程。
本系统就是以Java实训周中所学到的知识设计,GUI图形用户界面使用JavaFX技术编写,界面使用少量的CSS层叠样式表来进行渲染,增强美感。数据持久层采用DAO模式,将数据库操作进行封装,把数据访问和业务逻辑进行分离,在原则上降低了代码的耦合性,提高了代码扩展性和系统的可移植性。最后通过关系型数据库Derby完成对驾考试题的存储。
本系统主要的目的是方便驾考考生和教练管理出现在驾驶技能考试上科目一、科目四的单选题和判断题,让用户轻松管理试题,但本项目依旧存在着许多的不足和可再提升、改进的空间,主要体现在下面几个方面:
(1) 本项目由于开发时间紧迫,在界面设计上过于简单,功能过少。可以在后序的改进中引入一些可视化的图表。
(2) 选取的数据库Derby有一些不足,Derby的定位是嵌入式小型数据库,在本项目这种事务并不复杂的应用上还是很不错的,但也经常有连接失败和安全性不足等问题。