JDBC 專欄總集篇

JDBC

概念

Java Data Base Connectivity (Java 連接數(shù)據(jù)庫)
JDBC,其實(shí)就是Java定義的一套和數(shù)據(jù)庫建立連接的規(guī)范(接口),
那么各家數(shù)據(jù)庫廠商,想要Java去操作各家的數(shù)據(jù)庫,
必須實(shí)現(xiàn)這套接口,
我們把數(shù)據(jù)庫廠商寫的這套實(shí)現(xiàn)類,稱之為數(shù)據(jù)庫驅(qū)動

沒有jdbc之前,
我們想用Java連接數(shù)據(jù)庫,需要進(jìn)行如下步驟:

沒有jdbc之前

雖然也不是非常麻煩,但是:

  1. 針對不同的數(shù)據(jù)庫,我們需要編寫不同的驅(qū)動代碼
  2. 每當(dāng)任意一家數(shù)據(jù)庫更新時,維護(hù)起來也是十分麻煩的

正是因?yàn)樯鲜鰞牲c(diǎn)致命麻煩,Java針對連接數(shù)據(jù)庫,提出了一套機(jī)制 —— JDBC

有jdbc之后

因此,JDBC有如下優(yōu)點(diǎn)
優(yōu)點(diǎn)

  1. 維護(hù)方便
  2. 數(shù)據(jù)庫廠商的底層實(shí)現(xiàn)改變,不影響Java應(yīng)用程序

一般地,jdbc的接口,都存放在:

JDK提供的

  1. java.sql.*
  2. javax.sql.*

包下


那么,現(xiàn)在本人來講解下使用JDBC的使用步驟:

使用步驟:

使用步驟

  1. 導(dǎo)入數(shù)據(jù)庫的驅(qū)動jar包
  2. 加載驅(qū)動jar包
  3. 獲取連接對象
  4. 獲取操作對象
  5. 開始操作
  6. 釋放資源

那么,現(xiàn)在本人來展示下JDBC的使用:

package edu.youzg.about_jdbc.core;

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

public class Demo {
    
    public static void main(String[] args) throws Exception {
        //2. 加載驅(qū)動jar包
        Class.forName("com.mysql.jdbc.Driver");
        String url = "jdbc:mysql://localhost:3306/dbstudy";
        String userName = "root";
        String password = "123456";
        //3. 獲取連接對象
        Connection connection = DriverManager.getConnection(url, userName, password);
        //4. 獲取操作對象
        Statement statement = connection.createStatement();
        String sql = "update test set emp_fname='Youzg'";
        //5. 開始操作
        int i = statement.executeUpdate(sql);
        if(i>0){
            System.out.println(i);
            System.out.println("修改成功");
        }else{
            System.out.println("修改失敗");
        }
        //6. 釋放資源
        connection.close();
        statement.close();
    }
    
}

本人先來展示下運(yùn)行前的表內(nèi)容:


運(yùn)行前 展示

現(xiàn)在,本人來展示下運(yùn)行后的表中數(shù)據(jù):


運(yùn)行后 展示

那么,本人對上述步驟的第2步進(jìn)行下講解:

  • execute(sql):
    用來執(zhí)行所有的SQL語句
    返回
    如果第一個結(jié)果ResultSet 對象,則返回 true;
    如果其為更新、計(jì)數(shù)或者不存在任何結(jié)果,則返回 false
  • executeUpdate(sql):
    用來執(zhí)行DML語句
    用來對表中數(shù)據(jù)進(jìn)行增、刪、改
    返回值
    影響的行數(shù)
  • executeQuery(sql):
    用來執(zhí)行DQl語句

結(jié)果集對象 ResultSet:

概念:
結(jié)果集對象,是我們執(zhí)行了查詢語句之后返回的一個查詢結(jié)果對象
ResultSet 對象具有指向其當(dāng)前數(shù)據(jù)行的光標(biāo)
最初,光標(biāo)被置于第一行之前。
next()方法將光標(biāo)移動到下一行;
因?yàn)樵摲椒ㄔ?ResultSet 對象沒有下一行返回 false
所以可以在 while循環(huán)中使用它來迭代結(jié)果集

例如:
現(xiàn)在我要查詢表中數(shù)據(jù):

package edu.youzg.about_jdbc.core;

import java.sql.*;

public class Demo2 {
    
    public static void main(String[] args) throws Exception{
        Class.forName("com.mysql.jdbc.Driver");
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/dbstudy", "root", "123456");
        Statement statement = connection.createStatement();
        String sql = "select * from test";
        ResultSet resultSet = statement.executeQuery(sql);
        while (resultSet.next()) {
            System.out.println(resultSet.getInt(1)
                    + "==" + resultSet.getString(2)
                    + "==" + resultSet.getString(3)
                    + "==" + resultSet.getString(4));
        }
        connection.close();
        statement.close();
        resultSet.close();
    }
    
}

那么,本人現(xiàn)在來展示下運(yùn)行結(jié)果:


查詢結(jié)果 展示

那么,還記得本人在《Java SE》專欄最后說的嗎?

等我們學(xué)習(xí)了數(shù)據(jù)庫的相關(guān)知識后,
用戶登錄信息就可以保存在數(shù)據(jù)庫中,就不用用一張配置表來保存了
這樣既簡化了注冊用戶的問題,也保證了用戶賬號信息的安全性

本人來給出一張保存用戶登錄信息的表:


用戶登錄表 展示

那么,現(xiàn)在本人僅來展示下檢驗(yàn)用戶信息的代碼:

package edu.youzg.about_jdbc.core;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Scanner;

public class LoginDemo {
    public static void main(String[] args) throws Exception {
        Scanner sc = new Scanner(System.in);
        System.out.println("請輸入用戶名");
        String username = sc.nextLine().trim();
        System.out.println("請輸入密碼");
        String password = sc.nextLine().trim();
        //使用JDBC登錄
        Class.forName("com.mysql.jdbc.Driver");
        //建立連接
        Connection conn = DriverManager.getConnection("jdbc:mysql:///dbstudy", "root", "123456");
        //獲取操作對象
        Statement statement = conn.createStatement();
        //發(fā)送sql語句判斷是否登錄成功
        String sql="select * from users where username='"+username+"' and password='"+password+"'";

        ResultSet resultSet = statement.executeQuery(sql);
        if(resultSet.next()){
            System.out.println("登錄成功");
        }else{
            System.out.println("登錄失敗");
        }
        //釋放資源
        conn.close();
        statement.close();
        resultSet.close();
    }
}

那么,本人來展示下運(yùn)行結(jié)果:


用戶登錄1 展示

其實(shí),上面的做法也是不安全的
本人現(xiàn)在來展示下為什么說是不安全的

用戶登錄2 展示

相信同學(xué)們這時候就疑惑了:為什么用戶登錄信息表中并沒有保存該登錄信息,卻能夠登陸呢?
答曰

請看我們最后拼出來的sql字符串:
select * from users where username='1' or '1'='1' and password='1' or '1'='1';

相信看到這里,同學(xué)們就明白了登陸成功的原因了。
而這種現(xiàn)象,我們也有專門的名詞來形容它 —— sql注入

那么,有沒有什么辦法能夠防止sql注入呢?
答曰:

預(yù)編譯操做對象 PreparedStatement


那么,現(xiàn)在本人來介紹下 預(yù)編譯操做對象 PreparedStatement

PreparedStatement:

使用步驟

  1. 連接對象.prepareStatement(sql);
  2. sql語句中的字段的值?問號占位
  3. 給sql語句中的問號賦值

本人現(xiàn)在來展示下PreparedStatement的使用:

package edu.youzg.about_jdbc.core;

import java.sql.*;
import java.util.Scanner;

public class LoginDemo1 {
    public static void main(String[] args) throws Exception {
        Scanner sc = new Scanner(System.in);
        System.out.println("請輸入用戶名");
        String username = sc.nextLine().trim();
        System.out.println("請輸入密碼");
        String password = sc.nextLine().trim();
        //使用JDBC登錄
        Class.forName("com.mysql.jdbc.Driver");
        //建立連接
        Connection conn = DriverManager.getConnection("jdbc:mysql:///dbstudy", "root", "123456");
        //獲取操作對象
        String sql="SELECT * FROM users WHERE username=? AND PASSWORD=?";
        //獲取一個預(yù)編譯操作對象  PreparedStatement
        PreparedStatement preparedStatement = conn.prepareStatement(sql); //把SQL語句給給這個預(yù)編譯操作對象
        //下來給問號賦值 參1.問號的順序,從1開始數(shù) 參數(shù)2 問號的值
        preparedStatement.setString(1,username);
        preparedStatement.setString(2,password);

        ResultSet resultSet = preparedStatement.executeQuery(); //這里就不要再傳入SQL語句
        if(resultSet.next()){
            System.out.println("登錄成功");
        }else{
            System.out.println("登錄失敗");
        }
        //釋放資源
        conn.close();
        preparedStatement.close();
        resultSet.close();
    }
}

那么,本人再來進(jìn)行下sql注入,來展示下運(yùn)行結(jié)果:


防止sql注入 展示

可以看到:預(yù)編譯操作對象的使用,放置了sql注入!


那么,為了方便我們之后的操作,本人來給出一個方便我們JDBC操作的工具類:

package edu.youzg.about_jdbc.utils;

import java.io.FileInputStream;
import java.sql.*;
import java.util.Properties;

/**
 * 此工具用于實(shí)現(xiàn)JDBC的基本 增、刪、改、查 操作
 */
public class JDBCUtils {
    private static String url;
    private static String user;
    private static String password;

    private JDBCUtils() {
    }

    static {
        try {
            //讀取配置文件中數(shù)據(jù)庫的配置
            Properties properties = new Properties();
            properties.load(new FileInputStream("JDBCStudy/src/jdbcConfig.properties"));
            //注冊驅(qū)動
            Class.forName(properties.getProperty("driver"));
            url = properties.getProperty("url");
            user = properties.getProperty("user");
            password =properties.getProperty("password");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static Connection getConnection() throws SQLException {
        Connection connection = DriverManager.getConnection(url, user, password);
        return connection;
    }

    public static void close(Connection connection, Statement statement) throws SQLException {
        if (connection != null) {
            connection.close();
        }
        if (statement != null) {
            statement.close();
        }
    }

    public static void close(Connection connection, Statement statement, ResultSet resultSet) throws SQLException {
        if (connection != null) {
            connection.close();
        }
        if (statement != null) {
            statement.close();
        }
        if (resultSet != null) {
            resultSet.close();
        }
    }

}

那么,相應(yīng)地,本人來給出一個配置文件:

driver=com.mysql.jdbc.Driver
#注意:這里的url是本人根據(jù)本人的數(shù)據(jù)庫信息配置的,同學(xué)們請根據(jù)自己的數(shù)據(jù)庫信息來給url賦值
url=jdbc:mysql://localhost:3306/dbstudy
user=root
password=123456

在本篇博文的最后,本人來講解下如何在JDBC中獲取自增長鍵的值:

獲取自增長鍵的值:

步驟

  1. 要獲取自增長鍵的值,需要在獲取操作對象時聲明一個參數(shù):
    Statement.RETURN_GENERATED_KEYS
    即:
PreparedStatement preparedStatement = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
  1. 當(dāng)數(shù)據(jù)插入成功后,就可以取出這個自增長鍵的值:
//獲取自增長鍵的結(jié)果集
ResultSet generatedKeys = preparedStatement.getGeneratedKeys();
while (generatedKeys.next()){
    keyValue = generatedKeys.getInt(1);
}
  1. 之后就可以對循環(huán)中每次取出的自增長鍵值做處理了
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容