第一个JDBC程序的问题

2021-02-06 16:42:37 172 0
tangjin

关闭资源

之前的第一个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语句块中:

第一个JDBC程序的问题

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();
    } 

}

收藏
分享
海报
0 条评论
172
上一篇:第一段JDBC代码 下一篇:sql注入问题和PreparedStatement

本站已关闭游客评论,请登录或者注册后再评论吧~

忘记密码?

图形验证码