关闭资源
之前的第一个JDBC程序中关闭资源这部分代码其实是有问题的,如下:
// 注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 获取连接Connection
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/monkey1024", "root", "monkey1024");
// 得到执行sql语句的对象Statement
Statement stmt = conn.createStatement();
// 执行sql语句,并返回结果
ResultSet rs = stmt.executeQuery("select id,name,password,email,birthday from t_user");
// 处理结果
while(rs.next()){
System.out.println(rs.getObject("id"));
System.out.println(rs.getObject("name"));
System.out.println(rs.getObject("password"));
System.out.println(rs.getObject("email"));
System.out.println(rs.getObject("birthday"));
System.out.println("------------");
}
// 关闭Connection
rs.close();
stmt.close();
conn.close();
倘若在"执行sql语句,并返回结果"这一步报出了异常,那程序就会停止,这样就导致后面关闭资源相关的代码无法执行,但是在报异常之前,conn和stmt已经创建好了,为了解决这个问题,可以将关闭资源代码的部分放到finally语句块中:
package com.monkey1024.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
* 正确关闭资源
*
*/
public class JDBC_Test02 {
public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
// 注册驱动
try {
Class.forName("com.mysql.jdbc.Driver");
// 获取连接Connection
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/monkey1024", "root",
"monkey1024");
// 得到执行sql语句的对象Statement
stmt = conn.createStatement();
// 执行sql语句,并返回结果
rs = stmt.executeQuery("select id,name,password,email,birthday from t_user");
// 处理结果
while (rs.next()) {
System.out.println(rs.getObject("id"));
System.out.println(rs.getObject("name"));
System.out.println(rs.getObject("password"));
System.out.println(rs.getObject("email"));
System.out.println(rs.getObject("birthday"));
System.out.println("------------");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 关闭Connection
try {
if(rs != null){
rs.close();
}
rs = null;
if(stmt != null){
stmt.close();
}
stmt = null;
if(conn != null){
conn.close();
}
conn = null;
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
jdk7和 JDBC4.1之后的正确关闭资源
Connection、Statement、ResultSet都继承了AutoCloseable接口,因此可以使用try-with-resources的方式关闭这些资源:
package com.monkey1024.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
* jdk7和 JDBC4.1之后的正确关闭资源
*
*/
public class JDBC_Test03 {
public static void main(String[] args) {
// 注册驱动
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
// 获取连接Connection
try (Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/monkey1024", "root",
"monkey1024");
// 得到执行sql语句的对象Statement
Statement stmt = conn.createStatement();
// 执行sql语句,并返回结果
ResultSet rs = stmt.executeQuery("select id,name,password,email,birthday from t_user")) {
// 处理结果
while (rs.next()) {
System.out.println(rs.getObject("id"));
System.out.println(rs.getObject("name"));
System.out.println(rs.getObject("password"));
System.out.println(rs.getObject("email"));
System.out.println(rs.getObject("birthday"));
System.out.println("------------");
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
重构之前写的JDBC代码
再来回顾下之前写的jdbc代码,就会发现里面的增删改查操作中很多代码是重复的,比如注册驱动、创建连接,倘若将来更换数据库或者用户名密码的话需要修改很多内容,这样可维护性不高,为了提高可维护性,可以将这些经常变换内容写到一个配置文件中,这里创建一个名为db.properties的文件:
driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/monkey1024
username=root
password=monkey1024
创建一个DBUtil的工具类,在这个类中注册驱动和获取连接:
package com.monkey1024.jdbc.util;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ResourceBundle;
public class DBUtil {
private static String driverClass;
private static String url;
private static String username;
private static String password;
static{
ResourceBundle rb = ResourceBundle.getBundle("db");
driverClass = rb.getString("driverClass");
url = rb.getString("url");
username = rb.getString("username");
password = rb.getString("password");
try {
//注册驱动
Class.forName(driverClass);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Connection getConnection() throws SQLException{
return DriverManager.getConnection(url, username, password);
}
}
在有注册驱动和获取连接的操作时,可以直接调用DBUtil工具类:
@Test
public void testSelect() {
// 获取连接Connection
try (Connection conn = DBUtil.getConnection();
// 得到执行sql语句的对象Statement
Statement stmt = conn.createStatement();
// 执行sql语句,并返回结果
ResultSet rs = stmt.executeQuery("select id,name,password,email,birthday from t_user")) {
// 处理结果
List<User> userList = new ArrayList<>();
while (rs.next()) {
User u = new User();
u.setId(rs.getInt("id"));
u.setName(rs.getString("name"));
u.setPassword(rs.getString("password"));
u.setEmail(rs.getString("email"));
u.setBirthday(rs.getDate("birthday"));
userList.add(u);
}
System.out.println(userList);
} catch (SQLException e) {
e.printStackTrace();
}
}