20.java-JDBC連接mysql數據庫詳解


1.JDBC介紹

jdbc(java database connectivity)為java開發者使用數據庫提供了統一的編程接口,它由一組java類和接口組成。

JDBC需要用到的類和接口有:

DriverManager、Connection、Statement、ResultSet         

 

2. mysql-connector-java下載

本機的mysql版本是5.7.26 win32的,所以本章訪問mysql都以該版本為例:

 

然后進入https://dev.mysql.com/downloads/connector/j/下載mysql-connector-java.jar包,用於連接mysql

如下圖所示,只有8.0.19版本,那我們下載它就好了,反正不管64位還是32位都能訪問:

 

下載解壓后,就有個mysql-connector-java-8.0.19.jar:

 

接下來就來測試,能不能訪問

 

3.JDBC使用過程

3.1 通過DriverManager. registerDriver(Driver driver)來注冊驅動程序

需要注意,new Driver的時候,需要選擇com.mysql.cj.jdbc.Driver:

 

因為com.mysql.jdbc.Driver已經被棄用了.

PS:也可以直接將DriverManager. registerDriver(Driver driver)改為:

Class.forName("com.mysql.cj.jdbc.Driver");
//加載一下這個類就可以注冊驅動,因為mysql Driver類的靜態代碼塊中已經調用了registerDriver()來注冊驅動程序.

 

3.2 然后通過 Connection DriverManager.getConnection(String url, String user, String password)來連接數據庫,並獲取Connection對象

url: 填入“jdbc:子協議://ip地址:端口號/數據庫名” ,如果是mysql則填入“jdbc:mysql://localhost:3306/數據庫名”

針對mysql-connector-java-8.0以上的版本,則還要追加"?characterEcoding=utf-8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true"

username:mysql用戶名

password:mysql密碼

 

3.3 通過Connection對象獲取statement對象

Statement statement = connection.createStatement();

 

3.4 通過statement對象的executeQuery(String)來執行查詢sql語句,並返回ResultSet數據庫結果集

比如:

ResultSet  resultSet = statement. executeQuery("select * from student");       //獲取student表里的數據

除此之外還有int executeUpdate(String sql)方法.用來實現INSERT、UPDATE 或 DELETE 語句,返回值表示執行sql語句之后影響到的數據行數 (后面示例有講)

 

3.5 然后通過ResultSet來讀出query內容

ResultSet常用方法如下:

boolean first();             //移到內容第一行數據處

boolean  last();             //移到內容最后一行數據處

int getRow() ;             //獲取當前光標處於的行號

boolean isLast()           //獲取光標是否位於此 ResultSet 對象的最后一行。

boolean   next();          //移到下一行數據處,然后就可以通過getXXX()獲取完當前一行數據后,則通過next()來移動到下行繼續getXXX(),直到next()返回為false為止

boolean   previous();     //移到上一行數據處

String getString(String columnLabel);  //獲取當前一行的columnLabel列名的內容                             

String  getString(int columnIndex);   //獲取當前一行的第columnIndex列的內容,第一列是從1開始的.

         String getInt (String columnLabel);  //獲取當前一行的columnLabel列名的內容                     

String  getInt(int columnIndex);  //獲取當前一行的第columnIndex列的內容,第一列是從1開始的.

 
//...除此之外,還有getFloat(),getLong(),getShort(),getURL(),getBoolean(),getRowId()

 PS:獲取到ResultSet后,必須先next()一次才能getXXX(),來獲取內容

 

3.6 訪問結束后,釋放Mysql資源(畢竟mysql連入個數是有限的) 

    try {
            if(resultSet!=null){
            resultSet.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } 
        try {
            if(statement!=null){
            statement.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        try {
            if(connection!=null){
            connection.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

 

4.本章要訪問的數據庫以students為例:

 

 

5.首先來寫JdbcUtils工具類

JdbcUtils工具類里主要寫getConnection(),releaseResc()這兩個類,這樣避免后續的重復代碼產生.

JdbcUtils.java代碼如下所示:

public class JdbcUtils {

    private static String driver;
    private static String url;
    private static String user;
    private static String pwd;

    static{
        
        driver = "com.mysql.cj.jdbc.Driver";
        url = "jdbc:mysql://localhost:3306/students?characterEcoding=utf-8&"    
                + "useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true";
    
        user = "root";
        pwd = "sql";
        
    }
    
    
    //獲取一個鏈接mysql的Connection對象
    static public Connection getConnection(){
        
        try {
            Class.forName(driver);
             Connection connection = DriverManager.getConnection(url,user,pwd);
             return connection;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        
    }
    
    /**
     * 釋放Mysql資源(畢竟mysql連入個數是有限的)    
     * @param resultSet 結果集
     * @param statement 
     * @param connection 鏈接
     */
    public static void releaseResc(ResultSet resultSet, Statement statement, Connection connection) {
    
        try {
            if(resultSet!=null){
            resultSet.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } 
        try {
            if(statement!=null){
            statement.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        try {
            if(connection!=null){
            connection.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

 

6.數據庫查詢示例

查詢所有學生的信息:

@Test
    public void jdbcQuery(){
        
        ResultSet resultSet = null;
        Statement statement = null;
        Connection connection = null;
        try {
            connection = JdbcUtils.getConnection();        //通過JdbcUtils獲取connection
            statement = connection.createStatement();
            
            String sql = "select * from student";
            
            resultSet = statement.executeQuery(sql);
        
            while(resultSet.next()){
                
                String name = resultSet.getString("name");
                String score = resultSet.getString("score");
                String classs = resultSet.getString("class");
                
                System.out.println("姓名:"+name+"  成績:"+score+"  班級:"+classs);
            }
            
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally {
            
            JdbcUtils.releaseResc(resultSet, statement, connection);        //釋放資源
        }
    }

打印如下所示:

 

 

7.數據庫插入示例

@Test
    public void jdbcInser(){
        
        ResultSet resultSet = null;
        Statement statement = null;
        Connection connection = null;
         
        try {
            connection = JdbcUtils.getConnection();
            statement = connection.createStatement();
            
            String name = "小f";
            int score = 99;
            String classs = "初2-4班";
            
            String sql = "INSERT INTO  student(name,score,class) "        
                       +" values('"+name+"','"+String.valueOf(score)+"','"+classs+"')";
            
            int result = statement.executeUpdate(sql); 
            //executeUpdate:用來實現INSERT、UPDATE 或 DELETE 語句,返回值表示執行sql語句之后影響到的數據行數 
            
            System.out.println("插入了"+result+"條數據");
            
            
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally {
            
            JdbcUtils.releaseResc(resultSet, statement, connection);        //釋放資源
        }
    }

運行打印:

 

查看數據庫:

 

8.數據庫更新示例

將所有低於60分的同學的成績改為0:

@Test
    public void jdbcUpdate(){
        
        ResultSet resultSet = null;
        Statement statement = null;
        Connection connection = null;
        
        try {
            connection = JdbcUtils.getConnection();
             statement = connection.createStatement();
            
        
            String sql = "update student  SET score='0'  WHERE  score<60";
            
            
            int result = statement.executeUpdate(sql); 
            //executeUpdate:用來實現INSERT、UPDATE 或 DELETE 語句,返回值表示執行sql語句之后影響到的數據行數 
            
            System.out.println("更新了"+result+"條數據");
            
            
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally {
            
            JdbcUtils.releaseResc(resultSet, statement, connection);        //釋放資源
        }
        
    }

查看數據庫:

 

 

9.SQL 注入攻擊

Statement采取直接編譯 SQL 語句的方式,扔給數據庫去執行,所以很容易進行被SQL注入攻擊.

比如:

我們登陸執行時需要執行:

statement.executeQuery("select id from users where name ='"+username+"' and password = '"+password+"'");

而黑客則將字符串直接改為:

statement.executeQuery("select id from users where name ='"+username+"' or '1==1' and password = '"+password+"'");

就可以直接亂輸入密碼也能實現登錄了,所以java中提供了另一個類PreparedStatement, 采用"?"占位符預編譯,再填充參數,用來避免SQL注入攻擊.

 

PreparedStatement類介紹

采用"?"占位符預編譯,再填充參數,然后通過setXXX()來填充參數.比如setString():

setString(int parameterIndex, String x);       //向第parameterIndex個占位符填入x內容
// parameterIndex:第一個?占位符是1,第二個是2....

//...除了該方法之外,還有setFloat(),setLong(),setBoolean()....等等

 

修改登錄界面之PreparedStatement使用如下所示:

public static boolean login(String username,String password){
          Connection connection = JdbcUtils.getConnection();                  //獲取
                  try {

                          String sql = "select id from users where username =? and password = ?"; //要運行的sql語句,通過?來替換登錄賬號和密碼

                          PreparedStatement preparedStatement = connection.prepareStatement(sql);

                          //第一個? 用username字符串去替換
                          preparedStatement.setString(1, username);

                          //第二個? 用password字符串去替換
                          preparedStatement.setString(2, password);

                          ResultSet resultSet = preparedStatement.executeQuery();

                          return resultSet.next();            //有值則返回true,否則返回false;

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

 

 

 

 

 

 


免責聲明!

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



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