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

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

一、用到的工具

1.eclipse+windowbuilder插件

2.MySQL数据库+SQLyog

 

二、涉及的知识点

1. MVC设计模式

2. Swing

3. JDBC+MySQL

 

三、框架搭建

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

总结:JAVA小项目——图书管理系统_第1张图片总结:JAVA小项目——图书管理系统_第2张图片 

【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软件中,点击“架构设计器”拖动要关联的两张表,如下图所示。

总结:JAVA小项目——图书管理系统_第3张图片


【JDBC】

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

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

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

总结:JAVA小项目——图书管理系统_第4张图片

 

四、代码总结

<一>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.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

总结:JAVA小项目——图书管理系统_第5张图片

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

【表格显示查询结果】拖入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按钮加入到一个组中,才能实现二选一(非此即彼)。



【表格点击对应显示】

/**
	 * 表格行点击事件处理
	 * 将选中的行的信息分别显示到面板中相应的项里
	 * @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

【图书信息修改】

/**
	 * 图书修改事件处理
	 * @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);//表单第一项选中
		}
	}


你可能感兴趣的:(JAVA)