您的位置:首页 > 编程语言 > Java开发

总结:JAVA小项目——图书管理系统

2017-02-06 11:49 876 查看
总结:JAVA小项目——图书管理系统一、用到的工具1.eclipse+windowbuilder插件2.MySQL数据库+SQLyog 二、涉及的知识点1. MVC设计模式2. Swing3. JDBC+MySQL 三、框架搭建按照MVC设计模式在eclipse中新建项目,导入项目中要用到的图标,在数据库中创建表(以及表之间的主外键关联),用JDBC知识成功连接数据库。 【JAVA MVC】即把一个应用的输入、处理、输出流程按照Model、View、Controller的方式进行分离,这样一个应用被分成三个层——模型层、视图层、控制层。M——Model(模型)。业务流程/状态的处理以及业务规则的制定。把抽象的概念化成一个个类,例如User、Book、BookType。V——View(视图)。视图接收来自Model的数据并显示给用户,以及将用户界面的输入数据和请求传递给Controller和Model。此部分用windowbuilder插件来实现。C——Controller(控制器)。这部分主要是用来连接Model和View这两部分,控制层收到请求后, 并不处理业务信息,它只把用户的信息传递给相应的Model,告诉模型做什么,选择符合要求的View返回给用户。关于用户交互的操作的方法函数写在这一部分。——包com.BookManager.dao用来写Controller这一模块;——包com.BookManager.model用来写Model这一模块;——包com.BookManager.view用来写View这一模块;另外,将多次使用的工具类都写在com.BookManager.util包中,如数据库连接、判断字符串是否为空。 【包images】下载好图标后,新建一个images包,将复制好的图标直接ctrl+v粘贴进来即可。包images用来存放项目中用到的图标和图片(http://www.easyicon.net/ ) 【数据库创建表】1.【varchar】数据库创建表时,对于userName等项应设置成varchar数据类型,char是定长的字符,varchar存储大小为输入数据字节的实际长度,而不是 n 个字节。2.【主外键关联】主键的主要作用是将记录和存放在其他表中的数据进行关联,在这一点上,主键是不同表中各记录间的简单指针,不能有重复的,不允许为空。外键是另一表的主键,可以有重复,可以是空值,用来和其他表建立联系用的。所以说,如果谈到了外键,一定至少涉及两张表。外键约束主要用来维护两个表之间数据的一致性。在SQLyog软件中,点击“架构设计器”拖动要关联的两张表,如下图所示。【JDBC】1.【数据库中创建表】t_User,设置用户名及密码。2.【驱动】下载MySQL相应的驱动包,新建jdbc文件夹,将包复制粘贴到此文件夹中,然后Build Path—>Addto Build Path,就将此包添加到项目中了。3.【按MySQL格式写代码】封装DbUtil类。代码中按下快捷键ctrl+shift+o要导入sql的包时,应选择jdbc的接口——java.sql.Connection,如下图所示。 四、代码总结<一>Model模块在Model中将抽象概念Book、BookType、User用代码变量描述出来,即创建实体的描述。Alt+Shift+s弹出自动生成语句的菜单(创建成员变量get()和set()方法)。用到包装类,以便能将基本类型当作对象处理。【特别注意】构造方法中形参的每一项(顺序)都要与数据库中相应表中的栏目名称和类型保持一致。此外,BooType类中重写了toString()的方法。因为把BookType类的对象当作参数传进去后,显示出来的并不是它里面的数据,而是它的地址。所以重写toString()方法来显示BookType类的对象里面的数据。 <二>Controller模块连接用户输入的数据和数据库里面的数据的操作。在其他类中用到这些类的方法时,要先new相应的对象。1.用户登录——UserDao.java实现用户登录数据库功能,即输入用户名和密码,如果数据库的t_user表中含有匹配的用户名和密码,就能登录成功。所以,此方法应该为User类型,传入参数为数据库连接和用户——public User login(Connection con, Useruser)throws Exception{}·先定义变量sql,赋予MySQL的原始语句;·调用prepareStatement()来预处理sql;·调用setString(),设置MySQL语句中占位符的内容;·调用executeQuery();返回ResultSet结果集。【注意】调用此方法后,已经执行了sql语句的查询功能,即比对查询数据库中是否有将要输入(占位符)的数据。而数据的接收(输入数据)是在View模块中实现的,两个模块的变量相互呼应。·判断查询数据库的结果集是否含有输入的记录if(rs.next()),如果有,则实例化用户对象,并对其记录进行设置。 public class UserDao {public User login(Connection con,User user)throws Exception{User resultUser = null;/*** PreparedStatement接口是Statementd的子接口,用于预编译SQL语句。* 预编译后的SQL语句被存储在PreparedStatement对象中,* 然后可以使用该对象多次高效率地执行该语句(比Statement的效率高)。** Statement执行SQL语句时不允许使用问号占位符参数* PreparedStatement执行SQL语句时可以使用占位符,执行SQL语句之前必须为这些参数传入参数值** PreparedStatement也提供了execute()、executeUpdate()、executeQuery()三个方法执行SQL语句,* 不过他们无需参数,因为PreparedStatement已经存储了预编译的SQL语句*/String sql = "select*from t_user where userName=? and password=?";PreparedStatement pstmt = con.prepareStatement(sql);pstmt.setString(1, user.getUserName());pstmt.setString(2, user.getPassword());ResultSet rs = pstmt.executeQuery();/*** 【注意】调用此方法后,已经执行了sql语句的查询功能,* 即比对查询数据库中是否有将要输入(占位符)的数据。* 而数据的接收(输入数据)是在View模块中实现的,* 两个模块的变量相互呼应。*/if(rs.next()){resultUser = new User();resultUser.setId(rs.getInt("id"));resultUser.setUserName(rs.getString("userName"));resultUser.setPassword(rs.getString("password"));}return resultUser;}}2.图书类别操作——BookTypeDao.java实现图书类别的添加、删除、查询显示和修改维护以及判断此类别是否含有图书。【SQL语句拼接】因为是动态查询,bookTypeName可能没有值,因此涉及到判断是否为空,所以要用“拼接”的方式来写SQL语句——·用StringBuffer暂存一下字符串;·符合判断条件时,用append拼接,拼接的SQL语句用and连接,之后再替换成where(因为在拼接的两段SQL语句中,where的位置可能会造成多个if时的混乱,所以采用替换的方式来处理);·用toString()将StringBuffer中的内容转换成字符串,再将字符串内容的第一个and替换成where,即正式的SQL语句。public ResultSet list(Connection con,BookType bookType) throws Exception{StringBuffer sb = new StringBuffer("select*from t_bookType ");//用StringBuffer暂存一下字符串if(StringUtil.isNotEmpty(bookType.getBookTypeName())){//因为是动态查询,bookTypeName可能没有值,所以要用“拼接”的方式来写SQL语句sb.append(" and bookTypeName like '%" +bookType.getBookTypeName()+"%'");}//先用toString()将StringBuffer中的内容转换成字符串,再将字符串内容的第一个and替换成where,即正式的SQL语句//在拼接的两段SQL语句中,where的位置可能会造成多个if时的混乱,所以采用替换的方式来处理PreparedStatement pstmt = con.prepareStatement(sb.toString().replaceFirst("and", "where"));return pstmt.ebeccxecuteQuery();} 
3.图书操作——BookDao.java实现图书的添加、查询、删除、修改。两个表的关联查询。 public class BookDao {/*** 图书信息添加* @param con* @param book* @return* @throws Exception*/public int add(Connection con , Book book)throws Exception{String sql = "insert into t_book values(null,?,?,?,?,?,?)";PreparedStatement pstmt = con.prepareStatement(sql);pstmt.setString(1, book.getBookName());/*** 【特别注意】对每一个"?"进行设置时都要与数据库中t_book表中的栏目名称和类型保持一致.* 比如:* 如果原t_book表中第6栏是price,则第六个"?"处就代表price,类型就是float,* 那么若执行pstmt.setString(6, book.getBookDesc());就会因为名称和类型不一致而报错*/pstmt.setString(2, book.getAuthor());pstmt.setString(3, book.getSex());pstmt.setInt(4, book.getBookTypeId());pstmt.setString(5, book.getBookDesc());pstmt.setFloat(6, book.getPrice());return pstmt.executeUpdate();//为什么不能方法返回值为void,并把return去掉——————//executUpdate()本身返回int类型,返回受影响的记录条数。//也便于后面根据返回值而进一步判断执行}/*** 图书信息查询* @param con* @param book* @return* @throws Exception*/public ResultSet list(Connection con ,Book book)throws Exception{//t_book表中的id关联到了t_bookType表的bookTypeId,所以要执行两个表的关联查询//t_book表的外键等于t_bookType表的主键StringBuffer sb = new StringBuffer("select * from t_book b,t_bookType bt where b.bookTypeId=bt.id");if(StringUtil.isNotEmpty(book.getBookName())){sb.append(" and b.bookName like '%"+book.getBookName()+"%'");//like模糊查询}if(StringUtil.isNotEmpty(book.getAuthor())){sb.append(" and b.author like '%"+book.getAuthor()+"%'");// '% "关键词" %' 比如 '%java%'}//此时才表示用户选中了图书类别。(类别选择框中“请选择”的ID在BookManageInterFrm中已设为-1)if(book.getBookTypeId()!=null&&book.getBookTypeId()!=-1){sb.append(" and b.bookTypeId="+book.getBookTypeId());}//		PreparedStatement pstmt = con.prepareStatement(sb.toString().replaceFirst("and", "where"));PreparedStatement pstmt = con.prepareStatement(sb.toString());//只能有一个where,所以不需要再把and替换成wherereturn pstmt.executeQuery();}/*** 图书信息删除* @param con* @param id* @return* @throws Exception*/public int delete(Connection con ,String id)throws Exception{String sql = "delete from t_book where id=?";PreparedStatement pstmt = con.prepareStatement(sql);pstmt.setString(1, id);return pstmt.executeUpdate();}/*** 图书信息修改* @param con* @param book* @return* @throws Exception*/public int update(Connection con,Book book)throws Exception{//要注意此处的顺序要与数据库中每一项的顺序严格一致!String sql = "update t_book set bookName=?,author=?,sex=?,bookTypeId=?,bookDesc=?,price=?where id=?";PreparedStatement pstmt = con.prepareStatement(sql);pstmt.setString(1, book.getBookName());pstmt.setString(2, book.getAuthor());pstmt.setString(3, book.getSex());pstmt.setInt(4, book.getBookTypeId());pstmt.setString(5, book.getBookDesc());pstmt.setFloat(6, book.getPrice());pstmt.setInt(7, book.getId());//要注意sql语句中要有"where id=?"return pstmt.executeUpdate();}}<三>View模块借助windowbuilder插件,新建类时new—>other—>windowbuilder记得将窗体部件重命名,以便代码中当作对象调用方法。并且相关部件要在开头声明(有些自动生成的代码没有在开头申明需要手动调整完善)【表格显示查询结果】拖入scrollPane,然后在它里面拖入Jtable,通过Jtable的model属性设置表的标题与行列数,注意一定要与数据库中的顺序类型保持一致。/*** 显示结果表单* @param book*/private void fillTable(Book book){DefaultTableModel dtm = (DefaultTableModel) bookTable.getModel();//提前将table组件改名dtm.setRowCount(0);//清空表单Connection con = null;try{con = dbUtil.getCon();ResultSet rs = bookDao.list(con, book);while(rs.next()){Vector v = new Vector();v.add(rs.getInt("id"));v.add(rs.getString("bookName"));v.add(rs.getString("author"));v.add(rs.getString("sex"));v.add(rs.getString("bookTypeName"));//与数据库的顺序、名称保持一致v.add(rs.getString("bookDesc"));v.add(rs.getFloat("price"));dtm.addRow(v);}}catch(Exception e){e.printStackTrace();}finally{try {dbUtil.closeCon(con);} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}【初始化下拉框】/*** 初始化下拉框* @param type*/private void fillBookType(String type){Connection con = null;try{con = dbUtil.getCon();ResultSet rs = bookTypeDao.list(con, new BookType());//在选择下拉框里添加未选择时的"请选择"if("search".equals(type)){BookType bookType = new BookType();bookType.setBookTypeName("请选择");bookType.setId(-1);//设置新添加的"请选择"的ID为-1this.s_bookTypeJcb.addItem(bookType);//将此项添加到下拉框中}while(rs.next()){BookType bookType = new BookType();bookType.setBookTypeName(rs.getString("bookTypeName"));bookType.setId(rs.getInt("id"));if("search".equals(type)){this.s_bookTypeJcb.addItem(bookType);}else if("modify".equals(type)){this.bookTypeJcb.addItem(bookType);}}}catch(Exception e){try {dbUtil.closeCon(con);} catch (SQLException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}}}【JRadioButton】要执行右键,setButtonGroup将两个JRadioButton按钮加入到一个组中,才能实现二选一(非此即彼)。【表格点击对应显示】/*** 表格行点击事件处理* 将选中的行的信息分别显示到面板中相应的项里* @param met*/private void bookTableMousePressed(MouseEvent met) {int row = this.bookTable.getSelectedRow();//获取的是行号//要与数据库中的各项顺序一致this.idTXT.setText((Integer) bookTable.getValueAt(row, 0)+"");//【注意】id在fillTable方法中是getInt类型//所以此处应为Integer类型,但是setText方法里面是String类型//采取的办法就是【(Integer)+""】形式来转成String。否则报错。//下面Float同理this.bookNameTXT.setText((String) bookTable.getValueAt(row, 1));this.authorTXT.setText((String) bookTable.getValueAt(row, 2));//"性别"是获取后在选项前勾选的,不能直接设置文本显示String sex = (String) bookTable.getValueAt(row, 3);if("男".equals(sex)){this.manJrb.setSelected(true);}if("女".equals(sex)){this.femaleJrb.setSelected(true);}//"图书类别"是下拉框显示,也不能直接设置文本显示String bookTypeName = (String) bookTable.getValueAt(row, 4);int n = bookTypeJcb.getItemCount();//下拉框bookTypeJcb中有n个项for(int i=0;i<n;i++){//遍历n个项,如果其中第i项(item)的名称与点击行的bookTypeName相同,则下拉框显示此i项BookType item = (BookType) bookTypeJcb.getItemAt(i);//【注意】此处获取的是图书类别对象,不是图书类别名称if(item.getBookTypeName().equals(bookTypeName)){this.bookTypeJcb.setSelectedIndex(i);//下拉框显示此i项}}this.bookDescTXT.setText((String) bookTable.getValueAt(row, 5));this.priceTXT.setText((Float) bookTable.getValueAt(row, 6)+"");}【图书信息修改】/*** 图书修改事件处理* @param evt*/private void bookUpdateActionPerformed(ActionEvent evt) {String id = idTXT.getText();//因为id是int类型,所以创建对象时传入参数要进行类型转换Integer.parseInt(id)if(StringUtil.isEmpty(id)){JOptionPane.showMessageDialog(null, "请选择要修改的图书");return;}String bookName = this.bookNameTXT.getText();String bookDesc = this.bookDescTXT.getText();String author = this.authorTXT.getText();String price = this.priceTXT.getText();if(StringUtil.isEmpty(bookName)){JOptionPane.showMessageDialog(null, "图书名称不能为空");return;//不能少了return}if(StringUtil.isEmpty(author)){JOptionPane.showMessageDialog(null, "图书作者不能为空");return;//不能少了return}if(StringUtil.isEmpty(price)){JOptionPane.showMessageDialog(null, "图书价格不能为空");return;//不能少了return}String sex = "";if(manJrb.isSelected())sex = "男";if(femaleJrb.isSelected())sex = "女";BookType bookType = (BookType) bookTypeJcb.getSelectedItem();int bookTypeId = bookType.getId();Book book = new Book( Integer.parseInt(id), bookName,  author,  sex,  bookTypeId,  bookDesc, Float.parseFloat(price) );Connection con = null;try{con = dbUtil.getCon();int updateNum = bookDao.update(con, book);if(updateNum==1){JOptionPane.showMessageDialog(null, "图书修改成功");resetValue();this.fillTable(new Book());//实时修改刷新表单}else{JOptionPane.showMessageDialog(null, "图书修改失败");}}catch(Exception e){e.printStackTrace();JOptionPane.showMessageDialog(null, "图书修改失败");}finally{try {dbUtil.closeCon(con);} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}private void resetValue() {this.idTXT.setText("");this.bookNameTXT.setText("");this.authorTXT.setText("");this.priceTXT.setText("");this.bookDescTXT.setText("");this.manJrb.setSelected(true);if(this.bookTypeJcb.getItemCount()>0)//图书类别不为空{this.bookTypeJcb.setSelectedIndex(0);//表单第一项选中}}
                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java