大二下因为有一门专业必修课为数据库原理,于是在完成了该课程要求的大作业之后,重新审视一遍当初的设计思路,并进行一些总结。
开发环境
系统:Windows10(64位)家庭版
数据库:Mysql
开发语言及工具:Java,采用IDEA进行开发(IDEA本身具有优秀的集成环境和丰富的插件)。对于UI部分采用了IDEA的可视化UI开发插件——JFormDesigner
大作业要求及最终成品的功能描述
会议室预定及租借管理系统
该系统主要针对会议室租借管理而设计的方案,该方案包括了会议室的信息管理、预约与取消预约和设备管理系统。
数据库系统的业务描述
用户:管理员 普通用户
主要功能:
1、会议室借还
2、设备更新与维护
3、费用统计
系统边界或限制:
普通用户:
浏览会议室的预约情况与设备、人数
预定与取消预订(仅限本用户的订单)
登记预定信息
上报设备状况
付款
管理员:
浏览和修改会议室状态、设备与人数
预定与取消预订(所有的订单)
收取用户缴费并修改用户待缴费用
界面设计:
本程序具有一定的缺陷,与实际的应用场景还存在着差距。但我个人认为能够在仅有的5天时间内从零开始搭建一个完整的应用程序,已经十分不易。这次大作业也是对我的一次锻练,在没有任何知识的情况下初步学习了数据库应用的一些简单结构和设计方式。对于后来在假期中的重构工作有非常大的帮助。
程序设计思路
简单来讲,数据库应用程序的核心在于:用户的UI界面所获取和修改的信息,如何与真正的后台的数据库进行交互。当前业界流行的BS设计架构,主要是把用户的操作限制在web网页端,因此程序通常由“web前端”和“server后端”组成。由于我们在当初开发时并没有任何的web编程基础,因此我们放弃了BS架构这个主流架构。但我们同时学习了这种分层的思想,在程序内部进行了“DB层——Service层——GUI层”的分层划分。
DB层:
负责数据库的连接、sql语句的传入与结果集的返还。
Service层:
负责实现程序的各种业务逻辑,并且初步处理数据库返还的结果集。
GUI层:
负责提供可视化界面,读取用户各种信息,将Service层初步处理的结果集进行进一步处理并呈现。
具体的项目结构如下,其中dal是DB层。Service层里,Appointment、Meetingroom、Requirement和User是简单的bean类,提供getter和setter方法;dao则是我们在程序层面实现的用户群体划分,Cuser是普通用户,仅拥有一些比较有限的读写权限,而Admin为管理员,拥有较为完整的读写权限。
特别的,Cuser和Admin其实是实现具体的业务操作的class,不同的读写权限对应不同的业务操作。从DBUtil传来的ResultSet也在这两个类的方法里实现了解析和格式转换,并且这些处理好的数据集将继续传给GUI层用以呈现。
具体代码实现
在第一次开发这个大作业的时候,我们组二人通过查阅资料后,决定采用JDBC来连接数据库并进行Mysql语句的操作。主要采用到Mysql-connector和Java.mysql的jdk包。
以下是DB层的代码,所有的sql语句都会以String类型的一个字符串传入这层,并将得到的查询结果以ResultSet返回给上层。
import java.sql.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.sql.Connection;//连接数据库
import java.sql.DriverManager;//驱动管理
import java.sql.ResultSet;//结果集返还
import java.sql.SQLException;//异常处理
import java.sql.Statement;//输入并执行sql语句
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author Al Zhao
*/
public class DBUtil {
static final String driver = "com.mysql.cj.jdbc.Driver";
static final String URL = "jdbc:mysql://localhost:3306/roommanage?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai";
//上面url为连接数据库,需根据具体情况来修改。
private static Connection con = null;
private static Statement smt = null;
private static ResultSet rs = null;
//定义一些连接参数,用作连接数据库、执行语句和返还结果。
private static Connection createConnection() { //建立连接,url为上面已经确定的数据库。
try {
Class.forName(driver);
return DriverManager.getConnection(URL, "root", "123456");
}
//异常处理
catch (SQLException e) {
System.out.println(e.getMessage());
e.printStackTrace();//自动抛错
} catch (java.lang.ClassNotFoundException e) {
System.out.println("Can't load Driver");
}
return null;
}
public static int runUpdate(String sql) throws SQLException {//传入了一个string的sql语句,用作smt的执行
int count = 0;
if (con == null) {
con = createConnection();
}
if (smt == null) {
smt = con.createStatement();//connection创建statement对象,将smt实体化
}
count = smt.executeUpdate(sql);
/*方法 executeUpdate 用于执行 INSERT、UPDATE 或 DELETE 语句以及 SQLDDL(数据定义语言)语句,
例如 CREATE TABLE 和 DROP TABLE。INSERT、UPDATE 或 DELETE语句的效果是修改表中零行或多行中的一列或多列。
executeUpdate 的返回值是一个整数,指示受影响的行数(即更新计数)。对于CREATE TABLE 或 DROP TABLE 等不操作行的语句,executeUpdate 的返回值总为零。
*/
if (smt != null) {
smt.close();
smt = null;
}
if (con != null) {
con.close();
con = null;
}//释放对象空间
return count;//这里会返还受影响的记录行数
}
//执行sql语句
public static ResultSet runQuery(String sql) throws SQLException {
if (con == null) {
con = createConnection();
}
if (smt == null) {
smt = con.createStatement();
}
return smt.executeQuery(sql);//执行单个sql语句,如select之类的
}
//释放所有对象空间
public static void realeaseAll() {
if (rs != null) {
try {
rs.close();
rs = null;
} catch (SQLException e) {
e.printStackTrace();
}
}
if (smt != null) {
try {
smt.close();
smt = null;
} catch (SQLException e) {
e.printStackTrace();
}
}
if (con != null) {
try {
con.close();
con = null;
} catch (SQLException ex) {
Logger.getLogger(DBUtil.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
//关闭连接
public static void closeConnection(Connection conn) {
System.out.println("...");
try {
if (conn != null) {
conn.close();
conn = null;
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
以下为Service层中的两个daoimpl的类,其中包含了主要的业务逻辑和具体操作,实现了封装sql语句和resultset结果集的解析和处理。
AdminImpl
import Service.Appointment;
import Service.Users;
import Service.dao.Admin;
import dal.DBUtil;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
public class Adminimpl extends Users implements Admin {
public Adminimpl() {
}
public Adminimpl(String uno, String uname, String phone, String mail, String password) {
super(uno, uname, phone, mail, password);
}
public Adminimpl(String uno, String password) {
super(uno, password);
}
@Override
public boolean logIn() {
String select = "select * from user where UNO='"+getUno()+"'and PW='"+getPassword()+"'and IDENTITY='admin';";
boolean isCorrect;
isCorrect = false;
try{
ResultSet rs = DBUtil.runQuery(select);
if(rs!=null){
isCorrect=rs.next();
DBUtil.realeaseAll();
}
}catch (SQLException se) {
Logger.getLogger(Cuserimpl.class.getName()).log(Level.SEVERE, null, se);
}
return isCorrect;
}
@Override
public void logOut() {
DBUtil.realeaseAll();
}
@Override
public Vector[] getAllmeetingroom() {
String select = "select * from room;";
Vector[] Data = new Vector[2];
Vector data = new Vector();
Vector colNames = new Vector();
colNames.add("会议室号");
colNames.add("设备状态");
colNames.add("会议室状态");
colNames.add("会议室位置");
try {
ResultSet rs = DBUtil.runQuery(select);
while (rs.next()){
Vector row = new Vector();
row.add(rs.getString("RNO"));
row.add(rs.getInt("RESTD"));
row.add(rs.getInt("RSTA"));
row.add(rs.getString("ROA"));
data.add(row);
}
DBUtil.realeaseAll();
Data[0] = data;
Data[1] = colNames;
return Data;
} catch (SQLException se) {
Logger.getLogger(Adminimpl.class.getName()).log(Level.SEVERE, null, se);
}
return null;
}
@Override
public boolean setMeetingroomstd(String Rno, int std) {
String update="update room set RSTA="+std+" where RNO='"+Rno+"';";
try{
DBUtil.runUpdate(update);
return true;
}catch (SQLException se) {
Logger.getLogger(Adminimpl.class.getName()).log(Level.SEVERE, null, se);
}
return false;
}
@Override
public Vector[] getAppointmentbydate(String date) {
String select = "select * from appointment where DATE='"+date+"';";
Vector[] Data = new Vector[2];
Vector data = new Vector();
Vector colNames = new Vector();
colNames.add("预约号");
colNames.add("用户号");
colNames.add("会议室号");
colNames.add("开始时间");
colNames.add("结束时间");
colNames.add("日期");
try{
ResultSet rs = DBUtil.runQuery(select);
while (rs.next()){
Vector row = new Vector();
row.add(rs.getInt("ANO"));
row.add(rs.getString("UNO"));
row.add(rs.getString("RNO"));
row.add(rs.getTime("STIME"));
row.add(rs.getTime("ETIME"));
row.add(rs.getDate("DATE"));
data.add(row);
}
DBUtil.realeaseAll();
Data[0] = data;
Data[1] = colNames;
return Data;
} catch (SQLException se){
Logger.getLogger(Adminimpl.class.getName()).log(Level.SEVERE, null, se);
}
return null;
}
@Override
public boolean addAppointment(Appointment appointment) {
String insert = "insert into appointment(UNO,RNO,STIME,ETIME,DATE) values('"
+getUno()+"','"+appointment.getRno()+"','"+appointment.getStartTime()+"','"
+appointment.getEndTime()+"','"+appointment.getDate()+"');";
try{
DBUtil.runUpdate(insert);
return true;
}catch (SQLException se) {
Logger.getLogger(Adminimpl.class.getName()).log(Level.SEVERE, null, se);
}
return false;
}
@Override
public boolean removeAppointment(Appointment appointment) {
int hours;
int pri=0;
int money;
hours = countTime(appointment.getStartTime(),appointment.getEndTime());
String delete = "delete from appointment where ANO="+appointment.getAno()+";";
try{
DBUtil.runUpdate(delete);
ResultSet rs = DBUtil.runQuery("select RPRI from room where RNO = '"+appointment.getRno()+"';");
while (rs.next()){
pri = rs.getInt("RPRI");
}
DBUtil.realeaseAll();
money = hours*pri;
DBUtil.runUpdate("update user set MONY=MONY-"+money+" where UNO = '"+appointment.getUno()+"';");
return true;
} catch (SQLException se) {
Logger.getLogger(Adminimpl.class.getName()).log(Level.SEVERE, null, se);
}
return false;
}
@Override
public boolean setEqupmentstd(String Pno, int std) {
String update = "update device set DAMAGE="+std+" where PNO='"+Pno+"';";
try {
DBUtil.runUpdate(update);
return true;
} catch (SQLException se) {
Logger.getLogger(Adminimpl.class.getName()).log(Level.SEVERE, null, se);
}
return false;
}
@Override
public boolean setUsermoney(String Uno, int ammount) {
String update = "update user set MONY=MONY-"+ammount+" where UNO='"+Uno+"';";
try {
DBUtil.runUpdate(update);
return true;
} catch (SQLException se) {
Logger.getLogger(Adminimpl.class.getName()).log(Level.SEVERE, null, se);
}
return false;
}
@Override
public boolean setMeetingroomEqup(String Rno, int std) {
String update = "update room set RESTD = "+std+" where RNO = '"+Rno+"';";
try {
DBUtil.runUpdate(update);
return true;
} catch (SQLException se) {
Logger.getLogger(Adminimpl.class.getName()).log(Level.SEVERE, null, se);
}
return false;
}
@Override
public boolean changePw() {
String update="update user set PW='"+getPassword()+"' where UNO='"
+getUno() +"';";
try{
DBUtil.runUpdate(update);
return true;
}catch (SQLException se){
Logger.getLogger(Adminimpl.class.getName()).log(Level.SEVERE, null, se);
}
return false;
}
@Override
public Vector[] getAllEqupment() {
String select = "select * from device;";
Vector[] Data = new Vector[2];
Vector data = new Vector();
Vector colNames = new Vector();
colNames.add("设备编号");
colNames.add("会议室号");
colNames.add("设备名字");
colNames.add("损坏情况");
try {
ResultSet rs = DBUtil.runQuery(select);
while (rs.next()) {
Vector row = new Vector();
row.add(rs.getString("PNO"));
row.add(rs.getString("RNO"));
row.add(rs.getString("PNAME"));
row.add(rs.getInt("DAMAGE"));
data.add(row);
}
DBUtil.realeaseAll();
Data[0] = data;
Data[1] = colNames;
return Data;
} catch (SQLException se) {
Logger.getLogger(Adminimpl.class.getName()).log(Level.SEVERE, null, se);
}
return new Vector[0];
}
@Override
public int showUsermonye(String Uno) {
int money=0;
String select = "select MONY from user where UNO='"+Uno+"';";
try{
ResultSet rs = DBUtil.runQuery(select);
while (rs.next()){
money = rs.getInt("MONY");
}
DBUtil.realeaseAll();
} catch (SQLException se) {
Logger.getLogger(Adminimpl.class.getName()).log(Level.SEVERE, null, se);
}
return money;
}
}
CuserImpl
package Service.daoimpl;
import Service.*;
import Service.dao.Cuser;
import dal.DBUtil;
import java.sql.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Date;
import java.util.logging.*;
public class Cuserimpl extends Users implements Cuser {
public Cuserimpl() {
}
public Cuserimpl(String uno, String uname, String phone, String mail, String password) {
super(uno, uname, phone, mail, password);
}
public Cuserimpl(String uno, String password) {
super(uno, password);
}
@Override
public boolean signIn(){
String insert = "insert into user values('"+getUno()+"','"+getUname()+"','"
+getPhone()+"','"+getMail()+"','user','"
+getPassword()+"',"+getMoney()+");";
try{
DBUtil.runUpdate(insert);
return true;
}catch (SQLException se){
Logger.getLogger(Cuserimpl.class.getName()).log(Level.SEVERE, null, se);
}
return false;
}
//实现注册
@Override
public boolean logIn() {
String select = "select * from user where UNO='"+getUno()+"'and PW='"+getPassword()+"';";
boolean isCorrect = false;
try{
ResultSet rs = DBUtil.runQuery(select);
if(rs!=null){
isCorrect=rs.next();
DBUtil.realeaseAll();
}
} catch (SQLException se) {
Logger.getLogger(Cuserimpl.class.getName()).log(Level.SEVERE, null, se);
}
return isCorrect;
}
@Override
public void logOut() {
}
@Override
public Vector[] select(Requirement requirement) {
String select = "select room.*,DATE,STIME,ETIME from room left join appointment on room.RNO=appointment.RNO where RSTA=1";
if(requirement.dateValid) {
select = select.concat(" and DATE ='"+requirement.date+"'");
}
if(requirement.haveProjector) {
select = select.concat(" and HPJT=1");
}
if(requirement.haveComputer) {
select = select.concat(" and HCMP=1");
}
if(requirement.haveAudio) {
select = select.concat(" and HADO=1");
}
if(requirement.maxPoeplenumValid) {
select = select.concat(" and RCA="+requirement.maxPeoplenum);
}
if(requirement.pricePerhourValid) {
select = select.concat(" and RPRI="+requirement.pricePerhour);
}
select = select.concat(";");
Vector[] Data;
Data = new Vector[2];
Vector data = new Vector();
Vector colNames = new Vector();
colNames.add("会议室号");
colNames.add("会议室位置");
colNames.add("承担人数");
colNames.add("价格");
colNames.add("日期");
colNames.add("预约开始时间");
colNames.add("预约结束时间");
try {
ResultSet rs = DBUtil.runQuery(select);
while (rs.next()){
Vector row = new Vector();
row.add(rs.getString("RNO"));
row.add(rs.getString("ROA"));
row.add(rs.getInt("RCA"));
row.add(rs.getInt("RPRI"));
row.add(rs.getString("DATE"));
row.add(rs.getString("STIME"));
row.add(rs.getString("ETIME"));
data.add(row);
}
DBUtil.realeaseAll();
Data[0] = data;
Data[1] = colNames;
return Data;
} catch (SQLException se) {
Logger.getLogger(Cuserimpl.class.getName()).log(Level.SEVERE, null, se);
}
return null;
}
@Override
public boolean changePw() {
//传进来的user是给Password赋值了的,Uno也是赋值了的。
String update="update user set PW='"+getPassword()+"' where UNO='"
+getUno() +"';";
try{
DBUtil.runUpdate(update);
return true;
}catch (SQLException se){
Logger.getLogger(Cuserimpl.class.getName()).log(Level.SEVERE, null, se);
}
return false;
}
@Override
public Vector[] getAllmeetingroom() {
String select = "select * from room where RSTA = 1;";
Vector[] Data = new Vector[2];
Vector data = new Vector();
Vector colNames = new Vector();
colNames.add("会议室号");
colNames.add("设备状态");
colNames.add("会议室价格");
colNames.add("会议室位置");
colNames.add("是否有投影仪");
colNames.add("是否有电脑");
colNames.add("是否有音响");
try {
ResultSet rs = DBUtil.runQuery(select);
while (rs.next()){
Vector row = new Vector();
row.add(rs.getString("RNO"));
row.add(rs.getInt("RESTD"));
row.add(rs.getInt("RPRI"));
row.add(rs.getString("ROA"));
row.add(rs.getString("HPJT"));
row.add(rs.getString("HCMP"));
row.add(rs.getString("HADO"));
data.add(row);
}
DBUtil.realeaseAll();
Data[0] = data;
Data[1] = colNames;
return Data;
} catch (SQLException se) {
Logger.getLogger(Adminimpl.class.getName()).log(Level.SEVERE, null, se);
}
return null;
}
@Override
public boolean book(Appointment appointment) {
if(!isBooked(appointment.getRno(),appointment.getStartTime(),appointment.getEndTime(),appointment.getDate())) {
String insert = "insert into appointment(UNO,RNO,STIME,ETIME,DATE) values ('"
+getUno()+"','"+appointment.getRno()+"','"+appointment.getStartTime()+"','"
+appointment.getEndTime()+"','"+appointment.getDate()+"');";
int hours;
int pri=0;
int money;
try{
DBUtil.runUpdate(insert);
hours = countTime(appointment.getStartTime(),appointment.getEndTime());
ResultSet rs = DBUtil.runQuery("select RPRI from room where RNO = '"+appointment.getRno()+"';");
while (rs.next()){
pri = rs.getInt("RPRI");
}
DBUtil.realeaseAll();
System.out.println(hours);
money = hours*pri;
System.out.println(money);
DBUtil.runUpdate("update user set MONY=MONY+"+money+" where UNO = '"+getUno()+"';");
return true;
} catch (SQLException se){
Logger.getLogger(Cuserimpl.class.getName()).log(Level.SEVERE, null, se);
}
}
return false;
}
@Override
public Vector[] showApp() {
String select = "select * from appointment where UNO='"+getUno()+"';";
Vector[] Data = new Vector[2];
Vector colNames = new Vector();
colNames.add("预约号");
colNames.add("工号");
colNames.add("会议室号");
colNames.add("开始时间");
colNames.add("结束时间");
colNames.add("日期");
Vector data = new Vector();
try{
ResultSet rs = DBUtil.runQuery(select);
while (rs.next()) {
Vector row = new Vector();
row.add(rs.getInt("ANO"));
row.add(rs.getString("UNO"));
row.add(rs.getString("RNO"));
row.add(rs.getTime("STIME").toString());
row.add(rs.getTime("ETIME").toString());
row.add(rs.getDate("DATE").toString());
data.add(row);
}
DBUtil.realeaseAll();
Data[0]=data;
Data[1]=colNames;
return Data;
} catch (SQLException se) {
Logger.getLogger(Cuserimpl.class.getName()).log(Level.SEVERE, null, se);
}
return null;
}
@Override
public boolean cancel(Appointment appointment) {
int hours;
int pri=0;
int money;
hours = countTime(appointment.getStartTime(),appointment.getEndTime());
String delete = "delete from appointment where ANO=" + appointment.getAno() + " and UNO='" + getUno() + "';";
try {
DBUtil.runUpdate(delete);
ResultSet rs = DBUtil.runQuery("select RPRI from room where RNO = '"+appointment.getRno()+"';");
while (rs.next()){
pri = rs.getInt("RPRI");
}
DBUtil.realeaseAll();
money = hours*pri;
DBUtil.runUpdate("update user set MONY=MONY-"+money+" where UNO = '"+appointment.getUno()+"';");
return true;
} catch (SQLException se) {
Logger.getLogger(Cuserimpl.class.getName()).log(Level.SEVERE, null, se);
}
return false;
}
@Override
public boolean report(Meetingroom meetingroom) {
String update = "update room set RESTD=1 where RNO='"+meetingroom.getRno()+"';";
try {
int count;
count = DBUtil.runUpdate(update);
if(count>0)
return true;
else
return false;
} catch (SQLException se) {
Logger.getLogger(Cuserimpl.class.getName()).log(Level.SEVERE, null, se);
}
return false;
}
private boolean isBooked (String Rno, String stime, String etime, String date) {
boolean isbooked = false;
Date Stime = new Date();
Date Etime = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
try{
Stime = sdf.parse(stime);
Etime = sdf.parse(etime);
} catch (ParseException pe) {
}
Time s = new Time(Stime.getTime());
Time e = new Time(Etime.getTime());
System.out.println("s:"+s);
System.out.println("e:"+e);
String select = "select STIME, ETIME from appointment where RNO='"+Rno+"' and DATE = '"+date+"';";
try {
ResultSet rs = DBUtil.runQuery(select);
while (rs.next()){
Time S = rs.getTime("STIME");
Time E = rs.getTime("ETIME");
if(!(s.after(E) || e.before(S))){
isbooked = true;
}
}
} catch (SQLException se) {
Logger.getLogger(Cuserimpl.class.getName()).log(Level.SEVERE, null, se);
}
return isbooked;
}
@Override
public int showMoney() {
int money=0;
String select = "select MONY from user where UNO='"+getUno()+"';";
try{
ResultSet rs = DBUtil.runQuery(select);
while (rs.next()){
money = rs.getInt("MONY");
}
DBUtil.realeaseAll();
} catch (SQLException se) {
Logger.getLogger(Cuserimpl.class.getName()).log(Level.SEVERE, null, se);
}
return money;
}
}
GUI层的代码个人认为没有什么参考价值和意义。我们的设计思路是首先设计每个业务操作对应的UI界面,当这个界面设计好以后,我们设置各种按钮并设置监听事件和监听器。最后连接各个业务界面。下面仅提供一些界面参考。