JDBC之使用Statement,PreparedStatement,ResultSet

1. 建立一個獲取Connection對象和關閉資源的工具類java

  在對數據庫進行CRUD(①查詢數據、②數據插入、③數據修改、④數據刪除)操做的時候,每個操做都須要獲取Connection對象,因此咱們就能夠把獲取Connection對象的過程抽離到一個工具類當中,下面是具體代碼。sql

public final class JdbcUtil {
    
    private JdbcUtil() {
    }

    private static String url = "jdbc:oracle:thin:@127.0.0.1:1521:ORCL";
    private static String user = "scott";
    private static String password = "tiger";

    // 經過靜態代碼塊加載驅動類
    static {
        try {
            Class.forName("oracle.jdbc.driver.OracleDriver");
        }
        catch (ClassNotFoundException e) {
            throw new ExceptionInInitializerError("加載驅動類出錯!!");
        }
    }

    // 獲取鏈接對象
    public static Connection getConnection() throws Exception {
        Connection connection = null;
        connection = DriverManager.getConnection(url, user, password);
        return connection;
    }

    // 關閉資源
    public static void close(Connection connection, ResultSet rs, Statement statement) {
        if (rs != null) {
            try {
                rs.close();
            }
            catch (SQLException e) {
                e.printStackTrace();
            }
            finally {
                if (statement != null) {
                    try {
                        statement.close();
                    }
                    catch (SQLException e) {
                        e.printStackTrace();
                    }
                    finally {
                        if (connection != null) {
                            try {
                                connection.close();
                            }
                            catch (SQLException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            }
        }
    }

}

  我把url,username,password放在了類中,也能夠將這些配置信息放入到配置文件中,通常的作法是放入到配置文件當中,此處就簡單些。將加載驅動類的方法放入到static靜態代碼塊當中,當調用getConnection靜態方法的時候,static靜態代碼塊會先執行,即會先加載驅動類。close()方法就是關閉Statement,Connection,ResultSet對象的資源。數據庫

2.  使用Statement對象ResultSet對象進行簡單CRUD(增刪改查)操做安全

  首先看一下Statement接口的文檔說明:oracle

  用於執行靜態SQL語句並返回它所生成的結果的對象。工具

  在默認狀況下,同一時間每一個Statement對象在只能打開一個ResultSet對象。所以,若是讀取一個ResultSet對象與讀取另外一個交叉,則這兩個對象必須是由不一樣的Statement對象生成的。若是存在某個語句的打開的當前ResultSet對象,則Statement接口中的全部執行方法都會隱式關閉它。url

  Statement的主要做用就是執行SQL語句而且返回它所生產的結果對象。Statement對象是經過Connection對象進行獲取的,經過Connection.createStatement()方法獲取Statement對象。經過執行Statement對象的executeQuery()方法進行查詢SQL,該語句返回單個ResultSet 對象。spa

  下面是簡單的代碼示例:code

public void read(String id, String password) {

    Connection connection = null; // 初始化一個鏈接對象
    Statement statement = null;   // 初始化一個語句對象
    ResultSet resultSet = null;   // 初始化一個結果集對象

    try {
        connection = JdbcUtil.getConnection();
        statement = connection.createStatement();
        resultSet = statement.executeQuery("select id, name from student where id = '" + id + "' and password = '" + password + "'");
            
        while (resultSet.next()) {
            System.out.println("id = " + resultSet.getInt("id") + ", name = " + resultSet.getString("name"));
        }

    } catch(SQLException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        JdbcUtil.close(connection, resultSet, statement);
    }

}

  模擬了一個簡單的查詢用戶信息的SQL,傳入id和password對數據庫進行查詢,而後輸出。SQL語句是經過傳入的值拼接而成,因此這樣就很容易被SQL注入。當我傳入的password值爲' or 1 = 1 or '的時候打印出來SQL語句以下:對象

  select id, name from student where id = 'rcx' and password = '' or 1 = 1 or ''

  所以就能夠查詢到用戶的信息,引發不安全的漏洞。通常帶參數的查詢都須要使用PreparedStatement對象

3.  使用PreparedStatement對象(即預處理語句對象)ResultSet對象進行簡單CRUD(增刪改查)操做

  首先看一下PreparedStatement接口,它繼承自Statement接口。PreparedStatement對象(即預處理語句對象)表示預編譯的SQL語句。SQL語句被預編譯並存儲在PreparedStatement對象中。而後能夠使用此對象屢次高效地執行該SQL語句。預處理語句對象是Connection對象(即鏈接對象)經過調用prepareStatement(sql)方法來獲取的,傳入的參數是還未預編譯的SQL語句(即原始的SQL語句),可是該SQL語句的特殊之處在於參數部分是用?來代替。2中的SQL語句的例子經過PreparedStatement類實現的代碼以下:

public void read1(String id, String password) {

    Connection connection = null;
    PreparedStatement pstmt = null;
    ResultSet resultSet = null;

    try {

        connection = JdbcUtil.getConnection();

        // 下面這條SQL語句是預編譯語句類的核心,該SQL語句不是經過傳入的值拼接而成。
        String sql = "select id, name from student where id = ? and password = ?";
        pstmt = connection.prepareStatement(sql);

        pstmt.setString(1, id);
        pstmt.setString(2, password);
            
        // 該方法是不帶參數的,不然執行的不是預處理(即預編譯)的SQL語句
        resultSet = pstmt.executeQuery();
            
        while (resultSet.next()) {
            System.out.println("id = " + resultSet.getInt("id") + ", name = " + resultSet.getString("name"));
        }

    } catch(SQLException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        JdbcUtil.close(connection, resultSet, pstmt);
    }

}

  由於PreparedStatement對象中包含的是預處理SQL語句,因此能夠有效地防止SQL注入的問題,同時還能夠提升一些效率。

  注意:

  resultSet = pstmt.executeQuery();

  因爲PreparedStatement接口繼承自Statement接口,因此也有executeQuery(sql)帶參數的方法,若是這樣寫的話那麼執行的就是父類接口當中的方法了,則執行的不是預處理的SQL語句。

4.  一些其餘的方法

  因爲執行數據查詢的語句是經過調用ResultSet對象的executeQuery()方法來實現的,在插入數據更新數據刪除數據操做是經過調用executeUpdate(SQL)方法來實現的。因此執行給定的SQL語句,該語句可能爲INSERT(插入數據)、UPDATE(修改數據)或DELETE(刪除數據)語句,或者不返回任何內容的SQL語句(如SQL DDL語句)。

  ResultSet對象的next()方法:將光標從當前位置向前移一行。ResultSet光標最初位於第一行以前;第一次調用next()方法使第一行成爲當前行;第二次調用使第二行成爲當前行,依此類推。

完整的CRUD代碼:

public class CRUD {

    public static void main(String[] args) throws SQLException {
        read();        
        // create();
        // update();
        // delete();
    }

    // 數據查詢
    static void read() throws SQLException {

        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;

        try {
            // 2.創建鏈接,獲取鏈接對象
            conn = JdbcUtils.getConnection();
            // conn = JdbcUtilsSing.getInstance().getConnection();
            // 3.建立語句,此處即SQL語句
            st = conn.createStatement();

            // 4.執行語句,數據查詢語句
            rs = st.executeQuery("select id, name, money, birthday from user");

            // 5.處理結果
            while (rs.next()) {
                System.out.println(rs.getObject("id") + "\t"
                        + rs.getObject("name") + "\t"
                        + rs.getObject("birthday") + "\t"
                        + rs.getObject("money"));
            }
        } finally {
            JdbcUtils.free(rs, st, conn);
        }
    }
        
    // 插入數據
    static void create() throws SQLException {
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;
        try {

            // 2.創建鏈接
            conn = JdbcUtils.getConnection();
            // conn = JdbcUtilsSing.getInstance().getConnection();
            // 3.建立語句
            st = conn.createStatement();

            String sql = "insert into user(name,birthday, money) values ('name1', '1987-01-01', 400) ";

            // 4.執行語句
            int i = st.executeUpdate(sql);

            System.out.println("i=" + i);

        } finally {
            JdbcUtils.free(rs, st, conn);
        }
    }

    // 修改數據
    static void update() throws SQLException {

        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;

        try {
            // 2.創建鏈接
            conn = JdbcUtils.getConnection();
            // conn = JdbcUtilsSing.getInstance().getConnection();
            // 3.建立語句
            st = conn.createStatement();

            String sql = "update user set money=money+10 ";

            // 4.執行語句
            int i = st.executeUpdate(sql);

            System.out.println("i=" + i);
        } finally {
            JdbcUtils.free(rs, st, conn);
        }
    }

    // 刪除數據
    static void delete() throws SQLException {

        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;

        try {

            // 2.創建鏈接
            conn = JdbcUtils.getConnection();
            // conn = JdbcUtilsSing.getInstance().getConnection();
            // 3.建立語句
            st = conn.createStatement();

            String sql = "delete from user where id>4";

            // 4.執行語句
            int i = st.executeUpdate(sql);

            System.out.println("i=" + i);

        } finally {
            JdbcUtils.free(rs, st, conn);
        }

    }

}
相關文章
相關標籤/搜索