10.1(java學習筆記)JDBC基本操作(連接,執行SQL語句,獲取結果集)


一、JDBC

  JDBC的全稱是java database connection java數據庫連接。

  在java中需要對數據庫進行一系列的操作,這時就需要使用JDBC。

  sun公司制定了關於數據庫操作的組接口,數據庫廠商需要按照這個接口編寫對應的實現類。

  數據庫廠商編寫的實現類就稱為數據庫驅動。

 

  java訪問數據庫流程:

  1.加載驅動:加載數據庫廠商提供的實現類。

     2.建立連接:建立程序與數據庫的連接

  3.SQL語句:執行相應SQL語句

  4.結果集:得到查詢結果。

 

二、JDBC訪問數據庫

  為了便於查看和操作數據庫可以下載數據庫可視化軟件(例如Navicat)。

  2.1准備工作:

    2.1.1 下載驅動

      首先我們需要下載數據庫廠商提供的JDBC驅動。

       2.1.2 導入驅動

      由於這些驅動是數據庫廠商實現的,並不在java本身的庫中,所以需要從外部導入到項目中。

      鼠標右擊項目名稱--->Bulid Path-->Configure Build Path... --> Libraries  --> Add External JARs...

      -->-->-->

      然后找到下載的JDBC驅動所在文件夾,選擇里面的mysql-connector-java-x.x.xx.jar,然后點擊OK即可。

      

      添加完畢后項目顯示添加的驅動。

      

 

  2.2加載驅動    

public class TestJDBC{
    public static void main(String[] args){
        try {
            //加載驅動
            System.out.println(Class.forName("com.mysql.cj.jdbc.Driver"));
            //調用froName("x")會初始化名為x的類
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
運行結果:
class com.mysql.cj.jdbc.Driver

  這樣就代表驅動已經加載好了,這里的“com.mysql.cj.jdbc”根據下載的JDBC版本不同可能會略有不同。

  一開始我寫的是com.mysql.jdbc,運行后控制台提示:

  Loading class `com.mysql.jdbc.Driver'.
  This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'.

  后來修改為com.mysql.cj.jdbc.Driver就沒有問題了,這個在網上查下就可以解決了。

    

  2.3建立連接:建立程序與數據庫的連接

    建立數據庫連接首先我們需要了解一個類:DriverManager。

    DriverManager:管理JDBC驅動的基本服務,作用於用戶和驅動程序之間。

    追蹤可用的驅動程序,並在數據庫和相關的驅動程序之間建立連接。

    

    主要方法:

    public static Connection getConnection(String url,String user, String password);

    //根據給定的url地址,嘗試建立數據庫連接。返回一個Connection對象。

    //user,password為用戶名和密碼。

    

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class TestJDBC{
    public static void main(String[] args){
        final String connectionUrl = "jdbc:mysql://localhost:3306/mybatis";
        String userName = "root";
        String passWord = "123456";
        try {
            //加載驅動
            System.out.println(Class.forName("com.mysql.cj.jdbc.Driver"));
            Connection conn = DriverManager.getConnection(connectionUrl,userName,passWord);
            //調用froName("x")會初始化名為x的類
            
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

運行后沒有報錯,代表基本的連接沒有問題,報錯的原因有很多,一般是url格式錯誤,或用戶名密碼錯誤。

 

  2.4SQL語句:執行相應SQL語句

    本例所用表結構: (數據庫名:mybatis,表名:tadd)

CREATE TABLE `tadd` (
  `id` varchar(50) NOT NULL,
  `tname` varchar(50) DEFAULT NULL,
  `tpwd` varchar(50) DEFAULT NULL,
  `tstudentnum` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

 

    上面通過getConnection()建立了連接,並且返回了一個Connection對象。

    我們來看下Connection對象的作用及方法。

    Connection:代表了一個與指定數據庫的連接,執行SQL語句返回並在連接上下文中返回結果。

    主要方法:

    Statement createStatement();//創建將SQL語句發送到數據庫的語句對象。

    PreparedStatement(String sql);//創建PreparedStatement對象。

 

    2.4.1 Statement

    Statement:主要用於執行靜態的SQL語句,並返回其生成的結果對象。

    主要方法:

    boolean execute(String sql);執行給定的sql語句,可能返回多個結果。

       

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

public class TestJDBC{
    public static void main(String[] args){
        final String connectionUrl = "jdbc:mysql://localhost:3306/mybatis";
        String userName = "root";
        String passWord = "123456";
        try {
            //加載驅動
            System.out.println(Class.forName("com.mysql.cj.jdbc.Driver"));
            Connection conn = DriverManager.getConnection(connectionUrl,userName,passWord);
            Statement sta = conn.createStatement();
            boolean b = sta.execute("INSERT INTO `mybatis`.`tadd`"
                    + "(`id`, `tname`, `tpwd`, `tstudentnum`) "
                    + "VALUES ('17', '17', '77', '777');");
            
            System.out.println("執行成功");    
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
運行結果:
class com.mysql.cj.jdbc.Driver
執行成功

我們使用可視化軟件查看,發現對應數據庫(mybatis)中,對應的表(tadd)里面添加了一條記錄。

 

Statement有個缺點,不能防止SQL注入。

例如:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

public class TestJDBC{
    public static void main(String[] args){
        final String connectionUrl = "jdbc:mysql://localhost:3306/mybatis";
        String userName = "root";
        String passWord = "123456";
        try {
            //加載驅動
            System.out.println(Class.forName("com.mysql.cj.jdbc.Driver"));
        //建立連接 Connection conn
= DriverManager.getConnection(connectionUrl,userName,passWord); // Statement sta = conn.createStatement(); String sql = "delete from tadd where id = 1 or 1=1"; Statement ps = conn.createStatement();//創建Statement對象 ps.execute(sql);//執行SQL語句 System.out.println("執行成功"); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
運行結果:
class com.mysql.cj.jdbc.Driver
執行成功

使用可視化軟件我們可以看到整個表的信息都被刪除了。

這時因為 where id = 1 or 1=1,關鍵就在后面的or 1=1,在滿足id = 1 或者 1=1的條件下刪除。

可1=1恆成立,加上兩者又是or的關系,所以所有信息都滿足刪除都被刪除了。

 

  2.4.2PreparedStatement

    上面我們是使用Statments來執行SQL語句,但它存在一定的缺點。

    這時我們可以使用PreparedStatement,它可以防止SQL注入。

 

    PreparedStatement:表示預編譯SQL語句的對象。

    SQL語句預編譯並存儲在PreparedStatement對象中。然后可以使用此對象多次高效地執行此語句。

    繼承自Statement接口,用於發送一個或多個待輸入參數的sql語句。

    主要方法:

    void setObject(int parameterIndex, Object x);//給指定的參數索引設置指定對象x。

    使用Oject的話不用在意參數類型,比較方便。

 

    除了Object作為參數類型外,還有一些設置具體類型的函數。

    void setNString(int parameterIndex, String value);給指定的參數索引設置指定的String類型的值。

    void setInt(int parameterIndex, int x);給指定的參數索引設置指定的int類型的值。

    void setXXX..(int parameterIndex, XXX x);設置對應類型的值,此處就不一一舉例了,詳見API。

 

    此處的參數索引代表占位符的位序,具體含義詳見下列代碼注釋。

    boolean execute();執行SQL語句

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class TestJDBC{
    public static void main(String[] args){
        final String connectionUrl = "jdbc:mysql://localhost:3306/mybatis";
        String userName = "root";
        String passWord = "123456";
        try {
            //加載驅動
            System.out.println(Class.forName("com.mysql.cj.jdbc.Driver"));
            Connection conn = DriverManager.getConnection(connectionUrl,userName,passWord);
        //    Statement sta = conn.createStatement();
            String sql = "INSERT INTO `mybatis`.`tadd`"
                    + "(`id`, `tname`, `tpwd`, `tstudentnum`) "
                    + "VALUES (?, ?, ?, ?)";//?代表占位符, parameterIndex分別為1,2,3,4
            PreparedStatement ps = conn.prepareStatement(sql);
            ps.setObject(1, "p1");//此處的1代表第一個占位符,即sql語句中第一個問號
            ps.setObject(2, "p2");//第二個占位符,后面參數代表該占位符所代表的值
            ps.setObject(3, "p3");//可用setNString(3,"p3")代替
            ps.setObject(4, "p4");
            ps.execute();//執行sql語句
            System.out.println("執行成功");    
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
運行結果:
class com.mysql.cj.jdbc.Driver
執行成功

可以將sql語句設置為 delete from tadd where id = ?

再將?設置為 1 or 1= 1,可以發現表中數據並沒有被全部刪除。

 

  2.5結果集:得到查詢結果。

    boolean excute();返回類型是布爾,如果執行SQL語句返回的是結果集則為true,其他防護false;

    一般select語句才會返回結果集,所以執行select語句execute()返回true.其余語句一般為false.

    excuteQuery();返回結果集,主要用於運行select語句。

    excuteUpdata():返回改變的行數,主要用於insert,update,delete語句。

 

       

    我們可以根據我們執行的語句,選擇合適的方法得到對應的返回值。

    Resultset:表示數據庫結果集的數據表,通常通過執行查詢數據庫的語句生成。

    主要方法:

    boolean next();//將游標移動一行,判斷當前移動后的一行是否有數據。

    例如,返回的結果集有,3行(編號依次為1,2,3),游標初始值為0,

    調用next()方法后移動到第一行,如果第一行有數據返回true,反之返回false.

    String getString(int columnLabel);//將當前行中指定列的內容轉換為字符串形式。

    注意這里的列從1開始計數,即數據庫表中第一列數字為1,第二列數字為2.

    

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class TestJDBC{
    public static void main(String[] args){
        final String connectionUrl = "jdbc:mysql://localhost:3306/mybatis";
        String userName = "root";
        String passWord = "123456";
        try {
            //加載驅動
            Class.forName("com.mysql.cj.jdbc.Driver");
            Connection conn = DriverManager.getConnection(connectionUrl,userName,passWord);
        //    Statement sta = conn.createStatement();
            String sql = "select * from tadd where id = ?";
            PreparedStatement ps = conn.prepareStatement(sql);
            ps.setObject(1,"p1");
            ResultSet rs = ps.executeQuery();//返回一個結果集對象 while(rs.next()){//判斷是否有數據
                System.out.println("查詢結果:" +//獲取對應列數據
                                   rs.getString(1) + "---" + 
                                   rs.getString(2) + "---" +
                                   rs.getString(3) + "---" +
                                   rs.getString(4));
            }
            System.out.println("執行成功");    
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
運行結果:
查詢結果:p1---p2---p3---p4
執行成功

 

數據庫查詢完畢后要將創建的各個對象依次關閉,一般是先創立的后關閉。

以上述代碼為例,關閉順序應該是Resultset-->PreparedStatement-->Connection.

關閉時最好為每一個對象添加一個try catch語句,不要將三個對象的關閉放在一個try catch中,

避免關閉其中一個出現異常時,導致其它對象沒有關閉。 

 

三、批處理

  當我們需要大量(比如上萬條)執行某一語句時,建議采用批處理這樣可以提高執行效率。

  由於PreparedStatement預編譯空間有限,當數據量較大時可能出現異常,所以建議使用Statement。

  基本操作和之前的沒有太大區別,只是使用了幾個方法。

  setAutoCommit(boolean autoCommit);設置自動提交,默認為true即自動提交,false不自動提交。

  addBatch(String sql);添加處理語句到批中。

  excuteBatch();提交批。

  commit();手動提交

 

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class TestJDBC{
    public static void main(String[] args){
        final String connectionUrl = "jdbc:mysql://localhost:3306/mybatis";
        String userName = "root";
        String passWord = "123456";
        Connection conn = null;
        Statement ps = null;
        ResultSet rs = null;
        try {
            //加載驅動
            Class.forName("com.mysql.cj.jdbc.Driver");
            //建立連接
            conn = DriverManager.getConnection(connectionUrl,userName,passWord);
            conn.setAutoCommit(false);//將自動提交設為false,即不進行自動提交
            String sql = "select * from tadd where id = ?";
            ps = conn.createStatement();
            //批處理
            for(int i = 0; i < 10000; i++){
                ps.addBatch("INSERT INTO `mybatis`.`tadd`"
                        + "(`id`, `tname`, `tpwd`, `tstudentnum`) "
                        + "VALUES ('"+i+"', 'p1', 'p2', 'p3');");
            }
            ps.executeBatch();
            conn.commit();//手動提交
            
            System.out.println("執行成功");    
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally{
            //依次關閉連接
            try {
                rs.close();
            } catch (Exception e) {
                // TODO: handle exception
            }
            try{
                ps.close();
            }catch(Exception e){
                
            }
            try{
                conn.close();
            }catch(Exception e){
            }
        }
    }
}
運行結果:
執行成功
查看數據庫可以看到添加了10000條數據。
批處理就相當於將一個批次的語句打包一起執行,這樣比一條一條單獨執行效率要高。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM