本小节将讲解图书管理系统的代码设计思路及关键代码的实现过程。由于本章所介绍的图书管理系统与第24章所介绍的学生管理系统有很多相似之处,例如都定义了数据库工具类DBUtil完成获取连接的操作,因此两章相同之处本章不会重复讲解。
25.2.1删除图书信息
删除图书信息时,不仅仅要向用户确认是否要进行删除操作,还要先检查该图书是否有外借的情况,一旦该图书有外借并且未归还的情况就不能删除该图书。如果在未归还该图书的情况下删除它,由于内链接的特性就会造成无法找到该书被哪位读者借阅的情况。删除图书前先要判断其外借数量是否大于0,其判断代码如下:
String strLendNum = (String) table.getValueAt(row, 8);// 获得借出量
int lendNum = Integer.parseInt(strLendNum);
if (lendNum > 0) {//如果此书尚有外借的情况
JOptionPane.showMessageDialog(BookPanel.this,
"该图书尚有外借,全部归还后才能删除!");
return;
}
25.2.2借阅图书
通常来讲,一个图书馆不会把某图书全部外借给读者,而会在馆内至少保存一本。因此,当把一本书借给某个读者时,需要完成以下判断:
- 某一图书总量减去借出量是不是小于等于1,如果是则不能再外借。
- 借书的读者编号是不是真实存在。
- 该读者是不是处于停用状态,如果处于停用状态则不能给该读者借书。
- 读者如果已经借阅了该图书并且尚未归还则不能再次借出该书。
以上判断中,第1步在打开借阅对话框前就可以进行,其代码写在BookPanel类的“删除”按钮事件处理程序中,其实现过程如下。
int row = table.getSelectedRow();
if (row >= 0) {
String totalNum = (String) table.getValueAt(row, 7);//总量
String lendNum = (String) table.getValueAt(row, 8);//借出量
if(Integer.parseInt(totalNum)-Integer.parseInt(lendNum)<=1) {
JOptionPane.showMessageDialog(BookPanel.this,
"图书剩余量过少,不能外借!");
}
...
}
而2-4步的判断只能在填写了读者编号后才能判断,因此这些代码写在LendDialog类中,其实现过程如下。
if (readerId.length() == 0) {// 如果编号为空
JOptionPane.showMessageDialog(LendDialog.this, "读者编号不能为空!");
return null;
}
if(ReaderDao.isReaderExists(readerId)==false) {
JOptionPane.showMessageDialog(LendDialog.this, "该读者不存在!");
return null;
}
if("停用".equals(ReaderDao.getStateById(readerId))) {
JOptionPane.showMessageDialog(LendDialog.this, "该读者的借书证处于停用状态,不能借书!");
return null;
}
if(RecordDao.isLendThisBook(readerId, recordId)) {
JOptionPane.showMessageDialog(LendDialog.this,"该读者已借阅此书并且未归还,不能重复借阅!");
return null;
}
经过判断如果认定可以完成此次借书,需要搜集借阅人编号、图书编号、借阅时间等各项信息把它们组成一个Record对象插入数据库中,同时还需把图书的借出量减1,最后弹出对话框提示用户借书操作已经成功。借阅代码位于LendDialog类中,其实现过程如下:
model.Record record = checkData();
if(record!=null) {
try {
RecordDao.insert(record);//插入借书
BookDao.AddLendNumById(record.getBookId(), 1);//图书借出量加1
JOptionPane.showMessageDialog(LendDialog.this, "借阅成功!\n请最晚于"+record.getRegReturnDate()+"归还图书!");
isUpdate = true;
LendDialog.this.dispose();
} catch (Exception ex) {
ex.printStackTrace();
}
}
25.2.3修改图书类型和出版社
修改图书类型后必须重新查询并重新在界面上显示数据库中的图书信息,这是因为表示图书的book表中仅有图书类型的编号而并无图书类型的名称,界面上所显示出的图书类型是通过连接查询得到的,因此必须再次经过连接查询才能显示出修改后的图书类型。为判断用户在打开了图书类型对话框后是否真的修改了图书类型,在BookDialog中定义了表示是否有修改数据的isUpdate属性,如果修改了图书类型,则把该属性的值设置为true,因此关闭对话框后只需要根据isUpdate的属性值就能判断出是否修改了图书类型,如果没有修改图书类型,则无需重新查询数据库。修改图书类型后系统执行的代码如下:
BookTypeDailog dialog = new BookTypeDailog();
if (dialog.isUpdate == true) {
showInfo(curPage);// 重新查询(等同于刷新)
}
修改图书类型和出版社的操作完全相同,故此处不在赘述。
25.2.4删除图书类型和出版社
删除图书类时需要判断是否有该类型的图书,如果有该类型的图书就不能删除这个类型,判断是否存在该类型的图书的代码如下:
int num = BookDao.getBookNum("book_type.id", id, BookDao.ACCURATE);
if (num > 0) {
JOptionPane.showMessageDialog(BookTypeDailog.this, "系统中还有该类型的图书,不能删除该类型!");
return;
}
在以上代码中,BookDao类的getBookNum()方法用以判断某种类型的图书的数量,如果这个数量大于0,则不能删除该类型的图书。
当从数据库中删除某个类型后,还要从列表中删除这个类型的数据并同时清空反写到文本框中的类型信息,这个过程的实现代码如下。
//从列表中删除数据
data.removeRow(row);
// 清空文本框
txtId.setText("");
txtName.setText("");
删除出版社信息的过程与删除图书类型的过程完全相同,故在此不再赘述。
25.2.5更新归还状态
当图书被外借时,在record表中会插入一条借阅记录,并设置这条记录的state写入“未还”,但如果超过60天后读者仍未归还图书,该条数据的state就应该被更新为“逾期未还”。判断是否要把“未还”更新为“逾期未还”的条件是当前日期已经超过了最晚归还日期,这个判断需要调用MySQL的timestampdiff()函数,这个判断被写在RecordDao的setExNonReturn()方法中,这个方法的实现过程如下。
//根据当前日期刷新未归还图书的状态
public static boolean setExNonReturn() throws Exception {
boolean isSuccess = false;
Connection con = null;
PreparedStatement pst = null;
try {
con = DBUtil.getConnection();
String sql = "update record set state='逾期未还' where timestampdiff(day,reg_return_date,curdate())>0 and state='未还'";
pst = con.prepareStatement(sql);
pst.executeUpdate();
isSuccess = true;
} catch (SQLException e) {
isSuccess = false;
throw e;
} finally {
DBUtil.close(null, pst, con);
}
return isSuccess;
}
每当进入系统时,都会在初始化窗体过程中执行setExNonReturn()方法完成归还状态的自动更新,用户也可以在借阅信息面板中单击“刷新”按钮手动更新状态。
25.2.6归还图书
当归还图书时,都要把借阅记录中的state字段从“未还”改为“归还”,但由于用户可能没有及时刷新归还状态,所以不能从列表中所显示的归还状态来判断应该把state字段更新为“按时归还”还是“逾期归还”。正确的做法是:在更新state字段时,根据当前日期是否已经超出最晚归还日期来判断应该把state字段值更新为“按时归还”还是“逾期归还”。归还图书的操作过程写在RecordDao类的returnBook()方法中,这个方法的实现过程如下:
// 还书
public static boolean returnBook(String id) throws Exception {
boolean isSuccess = false;
Connection con = null;
PreparedStatement pst = null;
try {
con = DBUtil.getConnection();
String sql = "update record set state = if (timestampdiff(day,reg_return_date,curdate())>0, '逾期归还','按时归还') where id=?";
pst = con.prepareStatement(sql);
pst.setString(1, id);
pst.executeUpdate();
isSuccess = true;
} catch (SQLException e) {
isSuccess = false;
throw e;
} finally {
DBUtil.close(null, pst, con);
}
return isSuccess;
}
本文字版教程还配有更详细的视频讲解,小伙伴们可以点击这里观看。