數據庫(七)——JDBC編程

JDBC:

Java提供的一套操作數據庫數據的應用編程接口,作用在於通過Java代碼操作數據庫;dk所提供的相應的編程接口;

JDBC組件:

  1. DriverManager:一系列的數據驅動程序,匹配連接使用通信協議從Java應用程序中獲取合適的數據庫驅動;
  2. Connection:所有和數據庫相關的上下文操作通過該接口提供,提供數據庫的事務操作,Statment對象等接口方法;
  3. Statment:使用創建該接口的對象來進行SQL語句的提交到數據庫;
  4. ResultSet:存放使用SQL查詢數據庫返回的結果,本身是一個Set集合,多條數據是需要遍歷才能拿到對應結果的;
  5. SQLException:所有JDBC操作異常的同意處理類;

JDBC編程步驟:

數據庫連接的4個核心配置:

  1. 提供JDBC連接MySQL數據庫,需要MySQL的驅動包;
  2. 請求數據庫的URL;
  3. 數據庫賬號;
  4. 數據庫密碼;

數據庫編程:

  1. 加載數據庫驅動;
  2. 獲取數據庫的連接;
  3. 創建Statement對象;
  4. 執行SQL語句;
  5. 處理結果集 ;

代碼:
在這裏插入圖片描述

public static void main(String[] args) {
        try {
            Class.forName("com.mysql.jdbc.Driver");
            Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test4", "root", "123456");
            Statement statement = connection.createStatement();
            String sql = "select * from student";
            ResultSet resultSet = statement.executeQuery(sql);

            while (resultSet.next()) {
                int sid = resultSet.getInt("sid");
                String sname = resultSet.getString("sname");
                int sage = resultSet.getInt("sage");
                String ssex = resultSet.getString("ssex");
                System.out.println(sid+"\t"+sname+"\t"+sage+"\t"+ssex);
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

運行結果:

1	趙雷	20	男
2	前殿	20	男
3	孫風	21	男
4	吳蘭	18	女
5	孫蘭	17	女

注意:
getString()、getInt()等這些方法會將數據一次性裝入內存,所以數據量過大的時候,內存會裝不下就會拋出異常,而getObject()方法是每次調用就去數據庫獲取數據,不會將數據一次性全部裝入內存;

SQL注入問題

SQL注入問題::
由於dao層中執行的SQL語句是拼接出來的,其中一部分內容是用戶從客戶端輸入的,當傳入的數據中包含SQL關鍵字,就有可能通過這些關鍵字來改變SQL語句,從而執行一些特殊的操作,這種就稱爲SQL注入問題;

比如,有如下這樣一張user表:
在這裏插入圖片描述

public class TestDemo4 {
    public static void main(String[] args) {
        //前端輸入  用戶名和祕密
        String name = "zhangsan";
        String passwd = "1=1 or 2345";
        boolean login = login(name, passwd);
        if (login) System.out.println("登陸成功");
        else System.out.println("登陸失敗");
    }

    /**
     * 模擬前後臺交互接口
     *
     * @param userName:用戶名
     * @param passwd:祕密
     * @return true:登陸成功  false:登陸失敗
     */
    public static boolean login(String userName, String passwd) {
        boolean result = false;
        try {
            //加載驅動
            Class.forName("com.mysql.jdbc.Driver");
            //獲取Connection連接
            Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/test5", "root", "123456");
            //獲取Statement對象
            Statement statement = connection.createStatement();
            String sql = " select * from user where name='"+userName+"' and passwd="+passwd+"";
            boolean b = statement.execute(sql);
            if(b) {
                result = true;
            }
           /*
            String sql = "select * from user where name = ? and passwd=?";
            PreparedStatement statement = connection.prepareStatement(sql);
            statement.setString(1, userName);
            statement.setString(2, passwd);

           //執行SQL
            ResultSet resultSet = statement.executeQuery();

            //結果處理
            if (resultSet.next()) {
                result = true;
            }*/
        } catch (ClassNotFoundException e) {
            e.printStackTrace();

        } catch (SQLException e) {
            e.printStackTrace();
        }

        return result;
    }
}

運行結果:
在這裏插入圖片描述
密碼明明是錯的,但是因爲SQL語句的改變1=1是成立的,所以它也能登陸成功,這就是SQL的注入問題,解決辦法就是用PreparedStatement(屏蔽的那部分代碼);

如何解決SQL注入問題:

  1. 採用預編譯的Statement對象;PreparedStatement採用預編譯機制將SQL語句的主幹和參數分別傳輸給數據庫,數據庫是可以分辨SQL語句中的主幹和參數,這樣即使SQL中帶有關鍵字,數據庫也僅僅是將其當作參數使用,關鍵字就不起作用;

與Statement語句一樣,PreparedStatement語句同樣可以完成向數據庫發送SQL語句,獲取數據庫操作結果的功能。PreparedStatement語句習慣地稱爲預處理語句。
Statement對象在每次執行SQL語句時都將該語句傳送給數據庫,然後數據庫解釋器負責將SQL語句轉換成內部命令,並執行該命令,完成相應的數據庫操作,這種機制,每次向數據庫發送一條SQL語句時,都要先轉化成內部命令,如果不斷的執行程序,就會加重解釋器的負擔,影響執行的速度。
而PreparedStatement對象,將SQL語句傳送給數據庫進行預編譯,以後需要執行同一條語句時就不再需要重新編譯,直接執行就可以了,這樣就大大提高了數據庫的執行速度。

儘量使用預編譯的PreparedStatement,PreparedStatement的主要優勢如下:

  • 防止SQL注入問題;
  • 使用預編譯機制可以提高執行效率(執行前已經完成解析,到時候直接運行即可);
  • SQL語句中的參數值是通過?的形式來代替參數,再使用PreparedStatement方法的set方法來設置參數值,相對於SQL直接拼接更加優雅;

PreparedStatement和Statement的區別:

  • 語法不同:PreparedStatement使用預編譯的SQL,Statement使用靜態的SQL;
  • 效率不同:PreparedStatement執行效率較高;
  • 安全性不同:PreparedStatement可以防止SQL注入;

JDBC提供的事務相關的操作:

通過Connection接口下的方法提供的,比如設置手動、自動提交、事務的提交、回滾等等;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章