关于Java小项目——图书管理系统的总结

====================

网上看完视频写完这个小项目后,总结一下自己遇到的问题。。。

一、开发环境

eclipse + widowbuilder

二、涉及到的技术

  • Java MVC模式
  • Swing
  • MySQL
  • JDBC

Java MVC模式

M——Model(模型)。用于处理应用程序数据逻辑的部分。建立相关的类来连接数据库存储数据,例如用户类,图书类,图书类别类,把能够抽象化成一个一个的类写在这一部分
V——View(视图)。所有用户看到的界面,写在这一部分。这次用windowbuilder的这一插件来写视图
C——Contraller(控制器)。这部分主要是用来连接Model和View这两部分的,关于用户交互的操作的方法函数写在这一部分

首先,创建了几个包用来写不同模块的代码!关于Java小项目——图书管理系统的总结_第1张图片
com.luo.Model一个包用来写Model这一模块
com.luo.View一个包用来写View这一模块
com.luo.Dao一个包用来写Controller这一模块
另外,还创建com.luo.Util一个包用来封装相关的工具类,例如我们会重复需要连接数据库,这时候就先封装好一个连接数据库的那一部分的 工具类。后面连接起来就方便多了。
com.luo.Image这个包是用来存放项目中用到的图标和图片
http://www.easyicon.net/ —> 用来找图标的网站

MySQL部分

关联了bookTypeId和Id
也就是说BookType数据库的id 代表着 Book中类别的Id,例如类型1,类型7,其中1和7就是BookType中的id

关于Java小项目——图书管理系统的总结_第2张图片

在com.luo.Util中封装了连接数据库的一个DbUtil类
首先需要4个成员变量:

  • 数据库的名字,”jdbc:mysql://localhost:3306/(这里写数据库的名字)”
  • MySQL的用户名
  • MySQL的密码
  • JDBC驱动的名字 “com.mysql.jdbc.Driver”

接下来是连接数据库的方法函数

  • 通过Class调用forName()
  • 然后通过DriverManager调用getConnection()
  • 最后返回一个Connection类型值

还有关闭数据库的方法函数

  • 通过传入的Connection类型的值调用Close()
/**
 * 连接数据库工具
 * @author Administrator
 *
 */
public class DbUtil {

    private String dbUrl = "jdbc:mysql://localhost:3306/db_book";
    private String UserName = "root";
    private String Password = "123456";
    private String jdbcName = "com.mysql.jdbc.Driver";

    /**
     * 连接数据库
     * @return
     * @throws Exception
     */
    public Connection getCon() throws Exception {
        Class.forName(jdbcName);
        Connection conn = DriverManager.getConnection(dbUrl, UserName, Password);
        return conn;
    }

    /**
     * 关闭数据库
     * @param conn
     * @throws Exception
     */
    public void Closecon(Connection conn) throws Exception {
        if( conn != null){
            conn.close();
        }
    }

Model模块

这次的小项目分别建立了User类Book类BookType类。其中,后面需要用到这些类的构造方法传入参数,所以注意,要构造一个不带参数的构造函数,这样后面就可以new一个空的类了。

以下是其中一个用户类的代码,

public class User {

    private int id;
    private String userName;
    private String password;

    public User() {
        super();
    } //不带参数的构造函数

    public User(String userName, String password) {
        super();
        this.userName = userName;
        this.password = password;
    } //带两个参数的构造函数

    /********************************** 
    分别创建成员变量get()和set()方法
    ***********************************/
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
}

还有一点,BooType类中重写了toString()的方法。当把BookType类的对象当作参数传进去,显示出来的并不是它里面的数据,而是它的地址。所以重写toString()方法来显示BookType类的对象里面的数据
后面只需用到BookType类中的一个成员变量BookTypeName

public String toString() {
        return BookTypeName; //直接返回BookTypeName
    }

Controller模块和JDBC

以下是其中一个Book类的数据交互的代码,也就是连接用户输入的数据和数据库里面的数据的操作

  • MySQL的语句,增删查改,String类型
  • 调用prepareStatement()来预处理,
  • 调用setString(),设置MySQL语句中?的内容
  • executUpdate(),返回int类型; 若execuQuer(); 返回ResultSet类型
package com.luo.Dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

import com.luo.Model.Book;
import com.luo.Model.BookType;
import com.luo.Util.StringUtil;

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());
        pstmt.setString(2, book.getAuthor());
        pstmt.setString(3, book.getSex());
        pstmt.setFloat(4, book.getPrice());
        pstmt.setInt(5, book.getBookTypeId());
        pstmt.setString(6, book.getBookDesc());
        return pstmt.executeUpdate();
    }

    /**
     * 查询
     * @param con
     * @param book
     * @return
     * @throws Exception
     */
    public ResultSet list(Connection con, Book book) throws Exception{
        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() +"%'");
        }
        if(StringUtil.isNotEmpty(book.getAuthor())){
            sb.append(" and b.author like '%"+ book.getAuthor() +"%'");
        }
        if(book.getBookTypeId()!=null && book.getBookTypeId()!=-1){
            sb.append(" and b.bookTypeId="+ book.getBookTypeId());
        }
        PreparedStatement pstmt = con.prepareStatement(sb.toString());
        return pstmt.executeQuery();
    }

    /**
     * 更新数据
     * @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=?, price=?, bookTypeId=?, bookDesc=? where id=?";
        PreparedStatement pstmt = con.prepareStatement(sql);
        pstmt.setString(1, book.getBookName());
        pstmt.setString(2, book.getAuthor());
        pstmt.setString(3, book.getSex());
        pstmt.setFloat(4, book.getPrice());
        pstmt.setInt(5, book.getBookTypeId());
        pstmt.setString(6, book.getBookDesc());
        pstmt.setInt(7, book.getId());
        return pstmt.executeUpdate();
    }

    /**
     * 删除数据
     * @param con
     * @param id
     * @return
     * @throws Exception
     */
    public int Delete(Connection con, int id) throws Exception {
        String sql = "Delete from t_book where id=?";
        PreparedStatement pstmt = con.prepareStatement(sql);
        pstmt.setInt(1, id);
        return pstmt.executeUpdate();
    }

    /**
     * 判断是否存在书
     * @param con
     * @param book
     * @return
     * @throws Exception
     */
    public boolean existBook(Connection con, String bookTypeId) throws Exception {
        String sql = "select * from t_book where bookTypeId =?";
        PreparedStatement pstmt = con.prepareStatement(sql);
        pstmt.setInt(1, Integer.parseInt(bookTypeId));
        ResultSet rs = pstmt.executeQuery();
        return rs.next();
    }
}

View模块

  • 登录界面
  • 主界面
    • 图书类别添加界面
    • 图书类别管理界面
    • 图书添加界面
    • 图书维护界面

通过windowbuilder插件来创建一个Frame
登录界面通过登录按钮跳到主界面
以下是登录按钮响应事件的操作

/**
     * 登录操作
     * @param e
     */
    private void loginActionPerformed(ActionEvent e) {      
        String userName = this.userNameTxt.getText();
        String password = new String(this.passwordTxt.getPassword());
        //判断输入是否为空
        if(StringUtil.isEmpty(userName)) {
            JOptionPane.showMessageDialog(null, "用户名不能为空");
            return;
        }
        if(StringUtil.isEmpty(password)){
            JOptionPane.showMessageDialog(null, "密码不能为空");
            return;
        }
        Connection conn = null;
        try {
            //连接数据库
            conn = dbUtil.getCon();
            User user = new User(userName, password);
            User correntUser = userdao.login(conn, user);
            if(correntUser != null){
              /**************************************  
              这里先调用dispose()的方法,把当前的界面关掉
              再通过new出新的主界面,跳转到主界面上去
              ***************************************/
                dispose();
                new MainFrame().setVisible(true);   

            } else {
                JOptionPane.showMessageDialog(null, "用户名或密码错误!");
            }

        } catch (Exception e1) {
            e1.printStackTrace();
        } finally {
            try {
                dbUtil.Closecon(conn);
            } catch (Exception e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
        }
    }

登录界面和主界面的类都是继承JFrame

从工具栏选择一个JDesktopPane放置到contenPane里面,将它重命名为table
点击menuBar的一个选项,让它弹出一个界面(通过windowbuilder插件创建一个JInternalFrame,该选项添加响应事件,通过table调用add()的方法把这个界面显示出来),这个界面的类继承JInternalFrame,只能出现在table里面

这里的BookTypeManagerFrame是其中一个继承JInternalFrame的类显示出的框会在主界面里面

//  监听菜单栏上的图书类别管理这一选项的响应
mntmNewMenuItem_2.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                BookTypeManagerFrame bookTypeManagerFrame = new BookTypeManagerFrame();//new出一个新的图书类别管理类
                bookTypeManagerFrame.setVisible(true); //设置可见
                table.add(bookTypeManagerFrame); //添加进来主界面上
            }
        });

这是主界面的结构图,menuBar和一个contenPane

关于Java小项目——图书管理系统的总结_第3张图片

关于Java小项目——图书管理系统的总结_第4张图片关于Java小项目——图书管理系统的总结_第5张图片

我们可以拖入JTextArea来放置图这样一大段文字描述图书的内容
但是呢,一开始拖入JTextArea进来视图显示是没有边框
所以呢,要在该界面对应的代码中加入

bookTypeDesc.setBorder(new LineBorder(new java.awt.Color(12, 157, 185), 1, false));

点击按钮监听事件操作。比如点击添加键,就从数据库中获取数据显示在界面上,其实就是对数据库的操作和数据放在界面上显示的处理

  • getText()获取用户输入的内容
  • 工具类DbUtil,连接数据库
  • 调用Controller模块里面的类的方法,实现相关操作
  • 连接完数据库记得关闭!
  • 中间加上一些业务逻辑判断

这是项目中,获取数据在JTextField控件显示的小例子
至于重置编辑框为空的操作就是简单地重写setText(“”)一下;

//通过对按钮的监听,具体实现代码创建一个AddActionPerformed()方法写在外面,这里执行AddActionPerformed()方法
btnNewButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                AddActionPerformed(e);
            }
        });
/**
     * 添加数据
     * @param evt
     */
    private void AddActionPerformed(ActionEvent evt) {
        String Name = bookTypeName.getText();
        String Desc = bookTypeDesc.getText();
        if(StringUtil.isEmpty(Name)){
            JOptionPane.showMessageDialog(null, "图书类别名称不能为空");
            return;
        } 
        BookType bookType = new BookType(Name, Desc);
        Connection con = null;
        try {
            con = dbUtil.getCon();
            int result = bookTypeDao.addBookType(con, bookType);
            if(result == 1){
                JOptionPane.showMessageDialog(null, "添加成功!");
                reset();
            } else {
                JOptionPane.showMessageDialog(null, "添加失败!");
            }

        } catch (Exception e1) {
            // TODO Auto-generated catch block
            JOptionPane.showMessageDialog(null, "添加失败!");
            e1.printStackTrace();
        } finally{
            try {
                dbUtil.Closecon(con);
            } catch (Exception e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
        }

    }

用一个表格来显示数据。拖入scrollPane,然后在它里面拖入Jtable,通过Jtable的model属性设置表的标题与行列数。接着可以通过表格Jtable的mousePressed,来响应鼠标操作,从而对表中点击到的那一行的数据操作,显示在JTextField上

/**
     * 填充列表
     * @param book
     */
    private void fillTable(Book book){
        DefaultTableModel dtm = (DefaultTableModel) bookTable.getModel();
        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.getString("id"));
                v.add(rs.getString("bookName"));
                v.add(rs.getString("author"));
                v.add(rs.getString("sex"));
                v.add(rs.getString("price"));
                v.add(rs.getString("bookDesc"));
                v.add(rs.getString("bookTypeName"));
                dtm.addRow(v);
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
this.fillTable(new Book()); //调用此填充表格的方法函数

点击鼠标响应事件

bookTypeTable.addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                bookTypeTableMousePressed(e);
            }
        });
/**
     * 点击图表显示事件
     * @param evt
     */
    private void bookTypeTableMousePressed(MouseEvent evt) {
        int row = bookTypeTable.getSelectedRow(); //获取当前的行号
        //界面上对应控件通过调用setText()来显示出那一行的数据
        idTxt.setText((String) bookTypeTable.getValueAt(row, 0));
        bookTypeNameTxt.setText((String) bookTypeTable.getValueAt(row, 1));
        bookTypeDescTxt.setText((String) bookTypeTable.getValueAt(row, 2)); 
    }

关于下面这两种选择的数据填充:

关于Java小项目——图书管理系统的总结_第6张图片

关于Java小项目——图书管理系统的总结_第7张图片

这两个控件分别重命名为s_bookTypeBox和m_bookTypeBox,通过这两个名字来调用addItem()函数填充数据
按照面向对象的思想,直接传入的参数是BookType类的对象,所以要重写该类的toString()方法(前面提到的)。

/**
     * 填充bookType
     * @param type
     */
    private void fillBookType(String type){
        Connection con = null;
        BookType bookType = null;
        try {
            con = dbUtil.getCon();
            ResultSet rs = bookTypeDao.list(con, new BookType());
            if("search".equals(type)){
                bookType = new BookType();
                bookType.setBookTypeName("请选择...");
                bookType.setId(-1);
                this.s_bookTypeBox.addItem(bookType);
            }
            while(rs.next()){
                bookType = new BookType();
                bookType.setBookTypeName(rs.getString("bookTypeName"));
                bookType.setId(rs.getInt("id"));
                if("search".equals(type)){
                    this.s_bookTypeBox.addItem(bookType);
                } else if("modify".equals(type)){
                    this.m_bookTypeBox.addItem(bookType);
                }
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
this.fillBookType("modify");
this.fillBookType("search");    

补充一下上面用到的list()
模糊查询

/**
     * 查询
     * @param con
     * @param bookType
     * @return
     * @throws Exception
     */
    public ResultSet list(Connection con, BookType bookType) throws Exception{
        StringBuffer sb = new StringBuffer("select * from t_booktype ");
        if(StringUtil.isNotEmpty(bookType.getBookTypeName())){
            sb.append("and bookTypeName like '%"+ bookType.getBookTypeName() +"%'");
        }
        PreparedStatement pstmt = con.prepareStatement(sb.toString().replaceFirst("and", "where"));
        return pstmt.executeQuery();
    }

你可能感兴趣的:(Java)