前面介绍了ResultSet的基本操作,知道怎么去获取数据库中当前行的字段值和如何封装结果集的数据到一个高级对象中去。接下来的代码就是释放资源,也就是close()方法的正确关闭方法学习。
1.释放资源代码
之前我们是这样写关闭资源
//关闭资源
rs.close();
stmt.close();
conn.close();
其实这种关闭方式是不对的,如果rs, stmt, conn三个对象任意一个发生了异常或者错误,其中有些对象是没有创建,没有创建的对象还能去调用claose方法吗。例如我们的SQL语句有问题,这里把单词from拼写成form。
package demo;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class JDBCTest {
public static void main(String[] args) throws SQLException, ClassNotFoundException {
//加载驱动
Class.forName("com.mysql.jdbc.Driver");
//获取连接Connection对象
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydatabase", "root", "123456");
//得到执行SQL语句的Statement对象
Statement stmt = conn.createStatement();
//执行SQL语句,这里是执行查询语句,得到一个虚拟表的结果对象
ResultSet rs = stmt.executeQuery("SELECT * FORM student");
//对结果进行处理,这里是打印
while(rs.next()) {
System.out.println(rs.getObject(1) + "\t" + rs.getObject(2) + "\t" + rs.getObject(3) + "\t"+ rs.getObject(4));
}
//关闭连接
rs.close();
stmt.close();
conn.close();
}
}
运行之后虽然控制台没有报错,但是Junit报错了:
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax;
check the manual that corresponds to your MySQL server version for the right syntax to use near 'FORM student' at line 1
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at
也就是说conn对象创建了,stmt对象也创建了,但是rs对象由于执行SQL发生错误,并没有创建成功,对象都没有创建成功,rs调用close()方法肯定执行不到这行代码。 所以,我们需要正确处理这样的异常。
2.正确关闭资源方式
正确的关闭资源代码是这样的
package demo;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class JDBCTest {
public static void main(String[] args) {
//获取连接Connection对象
Connection conn = null;
//得到执行SQL语句的Statement对象
Statement stmt = null;
//执行SQL语句,这里是执行查询语句,得到一个虚拟表的结果对象
ResultSet rs = null;
try {
//加载驱动
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydatabase", "root", "123456");
stmt = conn.createStatement();
rs = stmt.executeQuery("SELECT * FROM student");
//对结果进行处理,这里是打印
while (rs.next()) {
System.out.println(
rs.getObject(1) + "\t" + rs.getObject(2) + "\t" + rs.getObject(3) + "\t" + rs.getObject(4));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//关闭连接
if(rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
rs = null; //赶紧垃圾回收
}
if(stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if(conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn = null;
}
}
}
}
我们来看看finally里面的close逻辑,我们知道try catch 语句块中,如果写了finally,那么无论如何代码一定都会去执行finally中的代码。一开始,我们判断如果rs不为空,那么我们在try catch语句块中尝试去关闭rs,try catch还是不行,里面直接把rs赋值成null,就是尽快让垃圾回收,释放资源。同理stmt和conn关闭的逻辑也是这样实现。这样就百分百确保一定能关闭,释放资源。