JDBC操作数据库(二) —— 查询操作

本文介绍如何优化JDBC的数据库查询操作,通过封装查询方法提高代码复用性,并解决因关闭ResultSet导致的异常问题。利用内部类和多态实现查询过程的优化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、数据库查询的常规方法

代码如下:

public static void main(String[] args) {
		Connection connection = null;
		Statement statement = null;
		ResultSet resultSet = null;
		try {
			//1.加载驱动
			Class.forName("com.mysql.jdbc.Driver");
			//2.建立连接
			connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test", "root", "root");
			//3.创建Statement对象
			statement = connection.createStatement();
			//4.书写SQL语句
			String sql = "select * from user_info";
			//5.执行SQL语句
			resultSet = statement.executeQuery(sql);
			//6.逐条查询数据库中的数据,并把信息并打印到控制台上
			while(resultSet.next()) {
				String id = resultSet.getString("id");
				String userName = resultSet.getString("user_name");
				String password = resultSet.getString("password");
				System.out.println(id+","+userName+","+password);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			//7.释放资源(注意顺序)
			try {
				if (resultSet!=null) {
					resultSet.close();
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
			
			try {
				if (statement!=null) {
					statement.close();
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
			
			try {
				if (connection!=null) {
					connection.close();
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
}

二、优化操作

与JDBC更新操作类似,对于查询不同的数据只是SQL语句不同,其他的步骤基本相同,如果每次进行更新操作,都要重新写一遍代码则代码复用性太差。
因此我们可以通过封装将查询功能的实现过程封装到该方法中,以便于以后重复调用。这样就增加了代码的复用性,进而达到优化代码的目的。
我们用与更新操作相似的方法尝试一下,代码如下:

public static ResultSet query(String sql) {
  	Connection connection = null;
  	Statement statement = null;
  	ResultSet resultSet = null;
  	try {
  		Class.forName("com.mysql.jdbc.Driver");
  		connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test", "root", "root");
  		statement = connection.createStatement();
  		return statement.executeQuery(sql);
  	} catch (Exception e) {
  		e.printStackTrace();
  	}finally {
  		try {
  			if (resultSet!=null) {
  				resultSet.close();
  			}
  		} catch (SQLException e) {
  			e.printStackTrace();
  		}
  		
  		try {
  			if (statement!=null) {
  				statement.close();
  			}
  		} catch (SQLException e) {
  			e.printStackTrace();
  		}
  		
  		try {
  			if (connection!=null) {
  				connection.close();
  			}
  		} catch (SQLException e) {
  			e.printStackTrace();
  		}
  	}
  	return null;
}

执行查询方法

public static void main(String[] args) {
	String sql = "select * from user_info";
	try {
		//query返回ResultSet对象
		ResultSet resultSet = query(sql);
		//逐条查询
		while(resultSet.next()) {
			String id = resultSet.getString("id");
			String userName = resultSet.getString("user_name");
			String password = resultSet.getString("password");
			System.out.println(id+","+userName+","+password);
		}
	} catch (Exception e) {
		e.printStackTrace();
	}
}

结果出现异常

java.sql.SQLException: Operation not allowed after ResultSet closed
	at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1055)
	at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:956)
	at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:926)
	at com.mysql.jdbc.ResultSetImpl.checkClosed(ResultSetImpl.java:794)
	at com.mysql.jdbc.ResultSetImpl.next(ResultSetImpl.java:7078)
	at test.TestQuery.main(TestQuery.java:53)

**这是由于当query方法执行完毕的时候已经把ResultSet关闭,而下面的代码继续执行query方法返回的ResultSet对象的next方法,所以出现了异常。**因此这里不能简单地返回一个ResultSet对象然后执行它的next()方法进行查询。

三、推荐优化代码

interface IRowMapper{//定义一个接口
	void rowMapper(ResultSet rs);//接口中有一个抽象方法,该方法需要传入一个ResultSet类型的参数
}

public class Select {
	public static void query(String sql,IRowMapper rowMapper) {
		Connection connection = null;
		Statement statement = null;
		ResultSet resultSet = null;
		try {
			Class.forName("com.mysql.jdbc.Driver");
			connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test", "root", "root");
			statement = connection.createStatement();
			resultSet = statement.executeQuery(sql);
			rowMapper.rowMapper(resultSet);//多态
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			try {
				if (resultSet!=null) {
					resultSet.close();
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
			try {
				if (statement!=null) {
					statement.close();
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
			try {
				if (connection!=null) {
					connection.close();
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}

在主方法中创建内部实现类重写rowMapper方法,实现多态,进而实现next()方法的重复运行

	public static void main(String[] args) {
		String sql = "select * from user_info";
		class RowMapper implements IRowMapper{//定义一个内部类实现该接口
			@Override
			public void rowMapper(ResultSet rs) {//重写抽象方法
				try {
					while(rs.next()) {
						String id = rs.getString("id");
						String userName = rs.getString("user_name");
						String password = rs.getString("password");
						System.out.println(id+","+userName+","+password);
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
		
		IRowMapper rowMapper = new RowMapper();//创建内部类对象
		query(sql,rowMapper);
	}
}

结果

111,111,111//此前创建表中已存入的数据
222,222,222

该方法利用多态和内部类很好的优化了JDBC实现查询过程的代码,解决了第一次优化过程中因提前关闭资源而导致无法继续执行next()方法的问题,从而提高了代码的复用性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值