java图书管理系统个人总结_总结:JAVA小项目——图书管理系统

本文总结了一款使用JAVA实现的图书管理系统,包括工具选择(Eclipse+WindowBuilder,MySQL+SQLyog),核心知识点(MVC设计模式,Swing,JDBC+MySQL),框架搭建步骤,以及各个模块的详细实现,如用户登录、图书类别操作和图书操作。通过对数据库表的创建,JDBC连接,和Swing界面设计,实现了功能齐全的图书管理系统。

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

一、用到的工具

1.eclipse+windowbuilder插件

2.MySQL数据库+SQLyog

二、涉及的知识点

1. MVC设计模式

2. Swing

3. JDBC+MySQL

三、框架搭建

按照MVC设计模式在eclipse中新建项目,导入项目中要用到的图标,在数据库中创建表(以及表之间的主外键关联),用JDBC知识成功连接数据库。

7302c1cb1f60a5558b4ba2b692a0bea9.png

54313d686b3c3a3b6672c34502e3cc95.png 

514209.html

514209.html

【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]存储大小为输入数据字节的实际长度,而不是 n 个字节。

2.【主外键关联】

主键的主要作用是将记录和存放在其他表中的数据进行关联,在这一点上,主键是不同表中各记录间的简单指针,不能有重复的,不允许为空。

外键是另一表的主键,可以有重复,可以是空值,用来和其他表建立联系用的。所以说,如果谈到了外键,一定至少涉及两张表。外键约束主要用来维护两个表之间数据的一致性。

在SQLyog软件中,点击“架构设计器”拖动要关联的两张表,如下图所示。

ee1264e4d0d8b05b2e4fd6d0b7afd397.png

514209.html

【JDBC】

1.【数据库中创建表】t_User,设置用户名及密码。

2.【驱动】下载MySQL相应的驱动包,新建jdbc文件夹,将包复制粘贴到此文件夹中,然后Build Path—>Addto Build Path,就将此包添加到项目中了。

3.【按MySQL格式写代码】封装DbUtil类。代码中按下快捷键ctrl+shift+o要导入sql的包时,应选择jdbc的接口——java.sql.Connection,如下图所示。

514209.html

a9bfca68504bbd3ed4d8a560446ba2a9.png

四、代码总结

Model模块

在Model中将抽象概念Book、BookType、User用代码变量描述出来,即创建实体的描述。

514209.html

aebe3889a8c2b4443b13f786ea623daf.png

Alt+Shift+s弹出自动生成语句的菜单(创建成员变量get()和set()方法)。

用到包装类,以便能将基本类型当作对象处理。

【特别注意】构造方法中形参的每一项(顺序)都要与数据库中相应表中的栏目名称和类型保持一致。

此外,BooType类中重写了toString()的方法。因为把BookType类的对象当作参数传进去后,显示出来的并不是它里面的数据,而是它的地址。所以重写toString()方法来显示BookType类的对象里面的数据。

514209.html

Controller模块

连接用户输入的数据和数据库里面的数据的操作。在其他类中用到这些类的方法时,要先new相应的对象。

514209.html

de037c2d18080671e0444404a74c6d66.png

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.executeQuery();

}

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替换成where

return 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

514209.html

ab3a2aa72943cb5477b347cb83d4c1a4.png

记得将窗体部件重命名,以便代码中当作对象调用方法。并且相关部件要在开头声明(有些自动生成的代码没有在开头申明需要手动调整完善)

【表格显示查询结果】拖入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 block

e.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为-1

this.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 block

e1.printStackTrace();

}

}

}

【JRadioButton】要执行右键,setButtonGroup将两个JRadioButton按钮加入到一个组中,才能实现二选一(非此即彼)。

514209.html

1080d420507c092a538b6c581e31feff.png

【表格点击对应显示】

/**

* 表格行点击事件处理

* 将选中的行的信息分别显示到面板中相应的项里

* @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

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 block

e.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);//表单第一项选中

}

}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值