1,用JAVA实现数据库连接后原始的查询代码·
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class Select {
public static void main(String[] args) {
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/keeper", "root", "root");
statement = connection.createStatement();
String sql = "select * from student";
resultSet = statement.executeQuery(sql);
while(resultSet.next()) {
String id=resultSet.getString("id");
String studentName=resultSet.getString("student_name");
String address=resultSet.getString("address");
String mobile=resultSet.getString("mobile");
System.out.println(id+":"+studentName+":"+address+":"+mobile);
}
} 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();
}
}
}
}
//考虑对查询语句的封装,实现代码的优化。
1)先来看一个简单的封装代码
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class Select {
//定义一个查询方法
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/keeper", "root", "root");
statement = connection.createStatement();
return statement.executeQuery(sql); //3,执行该语句后,查询完毕,随后释放资源
} catch (Exception e) {
e.printStackTrace();
}finally { //4,释放资源,回到main方法。
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; //上一个return不一定百分百执行,如果不执行返回null
}
public static void main(String[] args) {
String sql = "select * from student"; //1,输入查询语句
try {
ResultSet resultSet = query(sql); //2,调用定义的查询方法,跳转执行方法中的代码
while(resultSet.next()) { //5,开始执行该语句时,资源已释放,resultSet 已关闭,不会有遍历。所以此次封装不能够达到效果。能否先不关闭资源进行遍历后再关闭资源?考虑接口和多态。
String id=resultSet.getString("id");
String studentName=resultSet.getString("student_name");
String address=resultSet.getString("address");
String mobile=resultSet.getString("mobile");
System.out.println(id+":"+studentName+":"+address+":"+mobile);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
2)再来看一个封装代码
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
//构造一个查询方法
public class Select { //3,执行查询方法,后边没有关闭资源代码
static Connection connection = null;
static Statement statement = null;
public static ResultSet query(String sql) {
try {
Class.forName("com.mysql.jdbc.Driver");
connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/keeper", "root", "root");
statement = connection.createStatement();
return statement.executeQuery(sql);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
String sql = "select * from student"; //1,输入查询语句
ResultSet resultSet =null;
try {
resultSet = query(sql); //2,调用构造的查询方法
while(resultSet.next()) { //4,遍历
String id=resultSet.getString("id");
String studentName=resultSet.getString("student_name");
String address=resultSet.getString("address");
String mobile=resultSet.getString("mobile");
System.out.println(id+":"+studentName+":"+address+":"+mobile);
}
} catch (Exception e) {
e.printStackTrace();
}finally { //5,释放资源
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();
}
}
}
}
//此时代码正确;查询语句得到了封装,对比最原始的查询代码可以看出并没有简化代码。
2,封装后的查询代码
//用多态(接口回调)实现查询代码的封装
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
//1,定义接口,接口不能创建对象,所以我们考虑创建一个接口实现类(创建内部类)
interface IRowMapper{
void rowMapper(ResultSet rs); //定义接口中的方法,传入遍历后的查询结果。
}
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); //6,执行查询语句,将查询的结果放到了ResultSet 类中
rowMapper.rowMapper(resultSet); //7,此处出现多态,因为内部类实现了接口,所以调用重写后的方法,回到了main方法中内部类中定义的RowMapper方法,就不会出现先释放资源。
} 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();
}
}
}
public static void main(String[] args) {
String sql = "select * from student";
//为什么要创建内部类?因为我们希望查询完成之后先执行遍历而不是关闭资源,即回到main方法,执行完遍历再到查询方法中释放资源。
//详细解释是:用内部类实现接口后,先创建内部类对象,【在其中重写接口中的RowMapper方法(将遍历语句放到这个方法中)】,再调用查询方法,查询完成后,在查询方法中用内部类对象调用重写后的方法。
class RowMapper implements IRowMapper{ //2,创建内部类,类RowMapper实现了接口IRowMapper
@Override //重写接口中的方法
public void rowMapper(ResultSet rs) {
try {
while(rs.next()) { //8,将查询到的结果遍历出来,此方法执行完毕后,又回到query方法中。
String id=resultSet.getString("id");
String studentName=resultSet.getString("student_name");
String address=resultSet.getString("address");
String mobile=resultSet.getString("mobile");
System.out.println(id+":"+studentName+":"+address+":"+mobile);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
//3,创建内部类对象
RowMapper rowMapper = new RowMapper();
query(sql,rowMapper); //4,调用查询方法
}
}
//总结:逻辑是,创建接口,用内部类实现接口和重写接口中的方法(将遍历写成一个方法),在查询方法中用内部类对象实现接口回调,进而遍历。