Java連接MySQL

来源:https://www.cnblogs.com/kohler21/archive/2022/06/09/16358865.html
-Advertisement-
Play Games

JDBC概述 JDBC(Java Data Base Connectivity,java資料庫連接)是一種用於執行SQL語句的Java API,可以為多種關係資料庫提供統一訪問,它由一組用Java語言編寫的類和介面組成。是Java訪問資料庫的標準規範。 JDBC提供了一種基準,據此可以構建更高級的工 ...


目錄

JDBC概述

JDBC(Java Data Base Connectivity,java資料庫連接)是一種用於執行SQL語句的Java API,可以為多種關係資料庫提供統一訪問,它由一組用Java語言編寫的類和介面組成。是Java訪問資料庫的標準規範。

JDBC提供了一種基準,據此可以構建更高級的工具和介面,使資料庫開發人員能夠編寫資料庫應用程式。

JDBC需要連接驅動,驅動是兩個設備要進行通信,滿足一定通信數據格式,數據格式由設備提供商規定,設備提供商為設備提供驅動軟體,通過軟體可以與該設備進行通信。

JDBC原理

Java提供訪問資料庫規範稱為JDBC,而生產廠商提供規範的實現類稱為驅動。

JDBC是介面,驅動是介面的實現,沒有驅動將無法完成資料庫連接,從而不能操作資料庫!每個資料庫廠商都需要提供自己的驅動,用來連接自己公司的資料庫,也就是說驅動一般都由資料庫生成廠商提供。

JDBC開發步驟

Java資料庫鏈接主要包括以下幾步:

  1. 註冊驅動
  2. 獲得連接
  3. 獲得語句執行平臺
  4. 執行sql語句
  5. 處理結果
  6. 釋放資源

導入驅動包(jar包)(以eclipse為例)

在項目文件夾下創建lib目錄,用於存放當前項目需要的所有jar包(上面下載的jar包)選擇jar包,右鍵執行build path / Add to Build Path

註冊驅動

JDBC規範定義驅動介面java.sql.Driver,MySql驅動包提供了實現類com.mysql.jdbc.Driver、DriverManager工具類,提供註冊驅動的方法 registerDriver(),方法的參數是java.sql.Driver,所以我們可以通過如下語句進行註冊:

DriverManager.registerDriver(new com.mysql.jdbc.Driver());

但是並不提倡使用這種方法,原因如下:

通過查詢com.mysql.jdbc.Driver源碼,我們發現Driver類“主動”將自己進行註冊
*/
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
    static {
        try {
            java.sql.DriverManager.registerDriver(new Driver());
        } catch (SQLException E) {
            throw new RuntimeException("Can't register driver!");
        }
    }
……
}

// 這樣會造成驅動被註冊兩次  而且這樣編碼不易於程式擴展和維護

通常開發我們使用Class.forName() 載入一個使用字元串描述的驅動類。
如果使用Class.forName()將類載入到記憶體,該類的靜態代碼將自動執行。
所以我們可以使用一下代碼來註冊驅動:

Class.forName("com.mysql.jdbc.Driver");

獲得連接

獲取連接需要方法 DriverManager.getConnection(url,username,password),三個參數分別表示,url 需要連接資料庫的位置(網址) username用戶名 password 密碼。

url比較複雜,下麵是mysql的url:
jdbc:mysql://localhost:3306/mydb
JDBC規定url的格式由三部分組成,每個部分中間使用冒號分隔。
第一部分是jdbc,這是固定的;
第二部分是資料庫名稱,那麼連接mysql資料庫,第二部分當然是mysql了;
第三部分是由資料庫廠商規定的,我們需要瞭解每個資料庫廠商的要求,mysql的第三部分分別由資料庫伺服器的IP地址(localhost)、埠號(3306),以及DATABASE名稱(mydb)組成。

代碼:Connection con = DriverManager.getConnection
(“jdbc:mysql://localhost:3306/mydb”,”root”,”root”);

獲得語句執行平臺

常用方法有以下三種:

  • int executeUpdate(String sql); --執行insert update delete語句.
  • ResultSet executeQuery(String sql); --執行select語句.
  • boolean execute(String sql); --執行select返回true 執行其他的語句返回false.
String sql = "某SQL語句";
獲取Statement語句執行平臺:Statement stmt = con.createStatement();

結果處理

執行insert、update、delete無需處理
我們使用ResultSet來處理結果,ResultSet實際上就是一張二維的表格,我們可以調用其boolean next()方法指向某行記錄,當第一次調用next()方法時,便指向第一行記錄的位置,這時就可以使用ResultSet提供的getXXX(int col)方法(與索引從0開始不同個,列從1開始)來獲取指定列的數據:

rs.next();//指向第一行
rs.getInt(1);//獲取第一行第一列的數據

常用方法有以下幾種:

  • Object getObject(int index) / Object getObject(String name) 獲得任意對象
  • String getString(int index) / Object getObject(String name) 獲得字元串
  • int getInt(int index) / Object getObject(String name) 獲得整形
  • double getDouble(int index) / Object getObject(String name) 獲得雙精度浮點型

釋放資源

與IO流一樣,使用後的東西都需要關閉!關閉的順序是先得到的後關閉,後得到的先關閉。

rs.close();
stmt.close();
con.close();

SQL 註入問題

假設有登錄案例SQL語句如下:

SELECT * FROM 用戶表 WHERE NAME = 用戶輸入的用戶名 AND PASSWORD = 用戶輸的密碼;

此時,當用戶輸入正確的賬號與密碼後,查詢到了信息則讓用戶登錄。但是當用戶輸入的賬號為XXX 密碼為:XXX’ OR ‘a’=’a時,則真正執行的代碼變為:

SELECT * FROM 用戶表 WHERE NAME = ‘XXX’ AND PASSWORD =’ XXX’  OR ’a’=’a’;

此時,上述查詢語句時永遠可以查詢出結果的。那麼用戶就直接登錄成功了,顯然我們不希望看到這樣的結果,這便是SQL註入問題。
為此,我們使用PreparedStatement來解決對應的問題。

預處理對象

使用PreparedStatement預處理對象時,建議每條sql語句所有的實際參數,都使用逗號分隔。

String sql = "insert into sort(sid,sname) values(?,?)";;
PreparedStatement預處理對象代碼:
PreparedStatement psmt = conn.prepareStatement(sql)

常用方法:
{% note info %} 執行SQL語句
int executeUpdate(); --執行insert update delete語句.
ResultSet executeQuery(); --執行select語句.
boolean execute(); --執行select返回true執行其他的語句返回false.
{% endnote %}
{% note warning %}

設置實際參數
void setXxx(int index,Xxxxx)將指定參數設置為給定Java的xx值。在將此值發送到資料庫時,驅動程式將它轉換成一個 SQL Xxx類型值。
{% endnote %}

預處理對象executeUpdate方法

通過預處理對象的executeUpdate方法,完成記錄的insertupdatedelete語句的執行。操作格式統一如下:

  • 註冊驅動
  • 獲取連接
  • 獲取預處理對象
  • SQL語句占位符設置實際參數
  • 執行SQL語句
  • 釋放資源

插入操作(insert)

實現向表中插入指定的新內容

public void demo01() throws Exception {
        // 1註冊驅動
        Class.forName("com.mysql.jdbc.Driver");
        // 2獲取連接
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "root");
        // 3獲得預處理對象
        String sql = "insert into sort(sname) values(?)";
        PreparedStatement stat = conn.prepareStatement(sql);
        // 4 SQL語句占位符設置實際參數
        stat.setString(1, "奢侈品");
        // 5執行SQL語句
        int line = stat.executeUpdate();
        System.out.println("新添加記錄數:" + line);
        // 6釋放資源
        stat.close();
        conn.close();
}

更新操作(update)

public void demo02() throws Exception {
        // 1註冊驅動
        Class.forName("com.mysql.jdbc.Driver");
        // 2獲取連接
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "root");
        // 3獲得預處理對象中
        String sql = "update sort set sname=? where sid=?";
        PreparedStatement stat = conn.prepareStatement(sql);
        // 4 SQL語句占位符設置實際參數
        stat.setString(1, "數位產品");
        stat.setInt(2, 1);
// 5執行SQL語句
        int line = stat.executeUpdate();
        System.out.println("更新記錄數:" + line);
        // 6釋放資源
        stat.close();
        conn.close();
}

刪除操作

public void demo03() throws Exception {
        // 1註冊驅動
        Class.forName("com.mysql.jdbc.Driver");
        // 2獲取連接
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "root");
        // 3獲得預處理對象
        String sql = "delete from sort where sid=?";
        PreparedStatement stat = conn.prepareStatement(sql);
        // 4 SQL語句占位符設置實際參數
        stat.setInt(1, 1);
// 5執行SQL語句
        int line = stat.executeUpdate();
        System.out.println("刪除記錄數:" + line);
        // 6釋放資源
        stat.close();
        conn.close();
}

預處理對象executeQuery方法

通過預處理對象的executeQuery方法,完成記錄的select語句的執行。操作格式統一如下:

  • 註冊驅動
  • 獲取連接
  • 獲取預處理對象
  • SQL語句占位符設置實際參數
  • 執行SQL語句
  • 處理結果集(遍歷結果集合)
  • 釋放資源

查詢操作

public void demo04() throws Exception {
        // 1註冊驅動
        Class.forName("com.mysql.jdbc.Driver");
        // 2獲取連接
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "root");
        // 3獲得預處理對象
        String sql = "select * from sort";
        PreparedStatement stat = conn.prepareStatement(sql);
        // 4 SQL語句占位符設置實際參數
    // 5執行SQL語句
        ResultSet rs = stat.executeQuery();
        // 6處理結果集(遍歷結果集合)
        while( rs.next() ){
            //獲取當前行的分類ID
            String sid = rs.getString("sid");//方法參數為資料庫表中的列名
            //獲取當前行的分類名稱
            String sname = rs.getString("sname");
            //顯示數據
            System.out.println(sid+"-----"+sname);
        }
        // 7釋放資源
        rs.close();
        stat.close();
        conn.close();
}
public void demo05() throws Exception {
        // 1註冊驅動
        Class.forName("com.mysql.jdbc.Driver");
        // 2獲取連接
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "root");
        // 3獲得預處理對象
        String sql = "select * from sort where sname=?";
        PreparedStatement stat = conn.prepareStatement(sql);
        // 4 SQL語句占位符設置實際參數
        stat.setString(1, "奢侈品");
// 5執行SQL語句
        ResultSet rs = stat.executeQuery();
        // 6處理結果集(遍歷結果集合)
        while( rs.next() ){
            //獲取當前行的分類ID
            String sid = rs.getString("sid");//方法參數為資料庫表中的列名
            //獲取當前行的分類名稱
            String sname = rs.getString("sname");
            //顯示數據
            System.out.println(sid+"-----"+sname);
        }
        // 7釋放資源
        rs.close();
        stat.close();
        conn.close();
}

JDBC工具類

“獲得資料庫連接”操作,將在以後的增刪改查所有功能中都存在,可以封裝工具類JDBCUtils。提供獲取連接對象的方法,從而達到代碼的重覆利用。
該工具類提供方法:public static Connection getConn ()。代碼如下:

/*
 * JDBC工具類
 */
public class JDBCUtils {
    public static final  String DRIVERNAME = "com.mysql.jdbc.Driver";
    public static final  String URL = "jdbc:mysql://localhost:3306/mydb";
    public static final  String USER = "root";
    public static final  String PASSWORD = "root";

    static {
        try {
            Class.forName(DRIVERNAME);
        } catch (ClassNotFoundException e) {
            System.out.println("資料庫驅動註冊失敗!");
        }
    }
    //提供獲取連接的方法
    public static Connection getConn() throws Exception {
        // 2. 獲得連接
        Connection conn = DriverManager.getConnection(URL, USER, PASSWORD);
        // 返回連接
        return conn;
    }
}

如圖片失效等問題,參閱公眾號文章:https://mp.weixin.qq.com/s/Nlmj6ObCdTeGCQXog_GBrw

歡迎關註我的公眾號,共同學習


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 目錄 一.簡介 二.效果演示 三.源碼下載 四.猜你喜歡 零基礎 OpenGL (ES) 學習路線推薦 : OpenGL (ES) 學習目錄 >> OpenGL ES 基礎 零基礎 OpenGL (ES) 學習路線推薦 : OpenGL (ES) 學習目錄 >> OpenGL ES 轉場 零基礎 O ...
  • 時間的獲取及時間各格式間的轉換是比較常用的操作,但一是多種語言經常容易弄混,二是同一種語言同一個功能可能有不同的實現函數,導致每次處理時間經常要百度所以來記錄一下。 另外個人真不喜歡同樣功能有多種寫法的形式,從理想角度說多種實現方式讓不同的人都能以其喜歡的方式進行編寫;但實際上當你忘記的時候,你就總 ...
  • 沙包和打傘的故事 美國在1961年到1972年組織實施的一系列載人登月飛行任務。目的是實現載人登月飛行和人對月球的實地考察,為載人行星飛行和探測進行技術準備,它是世界航天史上具有劃時代意義的一項成就。阿波羅計劃始於1961年5月,至1972年12月第6次登月成功結束,歷時約11年,耗資255億美元。 ...
  • 一、分詞 - jieba 優秀的中文分詞庫,依靠中文詞庫,利用詞庫確定漢子之間關聯的概率,形成分詞結果 import jieba word = '偉大的中華人民共和國' jieba.cut(word) jieba.lcut(word) 二、詞雲庫 - wordcloud 對數據中出現頻率較高的 關鍵 ...
  • pom版本 <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>2.2.7</version> </dependency> 1.自定義合併單元格 在某些業務場景中可能會有合併單 ...
  • 主要內容 1·學習java日誌體系及日誌工具的演進 2·瞭解日誌採集、處理、分析等各階段的常用中間件 3·學會搭建完整的elk日誌平臺 4·學習日誌打點,切麵,日誌文件等輸出手段 5·項目實戰,完成一訪問日誌鏈路的跟蹤 1、Java日誌體系 1.1 體系概述 1.1.1 日誌介面 JCL:Apach ...
  • 前面我們詳細介紹了SSO、OAuth2的定義和實現原理,也舉例說明瞭如何在微服務框架中使用spring-security-oauth2實現單點登錄授權伺服器和單點登錄客戶端。目前很多平臺都提供了單點登錄授權伺服器功能,比如我們經常用到的QQ登錄、微信登錄、新浪微博登錄、支付寶登錄等等。 如果我們自己 ...
  • 一個工作了3年的粉絲,去一個互聯網公司面試,結果被面試官懟了。 面試官說:”這麼簡單的問題你都不知道? 沒法聊了,回去等通知吧“。 這個問題是: ”什麼是可重入鎖,以及它的作用是什麼?“ 對於這個問題,來看看普通人和高手的回答吧 普通人: 嗯。。。。。。。。。。。。。。。。。。 高手: 好的。 可重 ...
一周排行
    -Advertisement-
    Play Games
  • C#TMS系統代碼-基礎頁面BaseCity學習 本人純新手,剛進公司跟領導報道,我說我是java全棧,他問我會不會C#,我說大學學過,他說這個TMS系統就給你來管了。外包已經把代碼給我了,這幾天先把增刪改查的代碼背一下,說不定後面就要趕鴨子上架了 Service頁面 //using => impo ...
  • 委托與事件 委托 委托的定義 委托是C#中的一種類型,用於存儲對方法的引用。它允許將方法作為參數傳遞給其他方法,實現回調、事件處理和動態調用等功能。通俗來講,就是委托包含方法的記憶體地址,方法匹配與委托相同的簽名,因此通過使用正確的參數類型來調用方法。 委托的特性 引用方法:委托允許存儲對方法的引用, ...
  • 前言 這幾天閑來沒事看看ABP vNext的文檔和源碼,關於關於依賴註入(屬性註入)這塊兒產生了興趣。 我們都知道。Volo.ABP 依賴註入容器使用了第三方組件Autofac實現的。有三種註入方式,構造函數註入和方法註入和屬性註入。 ABP的屬性註入原則參考如下: 這時候我就開始疑惑了,因為我知道 ...
  • C#TMS系統代碼-業務頁面ShippingNotice學習 學一個業務頁面,ok,領導開完會就被裁掉了,很突然啊,他收拾東西的時候我還以為他要旅游提前請假了,還在尋思為什麼回家連自己買的幾箱飲料都要叫跑腿帶走,怕被偷嗎?還好我在他開會之前拿了兩瓶芬達 感覺感覺前面的BaseCity差不太多,這邊的 ...
  • 概述:在C#中,通過`Expression`類、`AndAlso`和`OrElse`方法可組合兩個`Expression<Func<T, bool>>`,實現多條件動態查詢。通過創建表達式樹,可輕鬆構建複雜的查詢條件。 在C#中,可以使用AndAlso和OrElse方法組合兩個Expression< ...
  • 閑來無聊在我的Biwen.QuickApi中實現一下極簡的事件匯流排,其實代碼還是蠻簡單的,對於初學者可能有些幫助 就貼出來,有什麼不足的地方也歡迎板磚交流~ 首先定義一個事件約定的空介面 public interface IEvent{} 然後定義事件訂閱者介面 public interface I ...
  • 1. 案例 成某三甲醫預約系統, 該項目在2024年初進行上線測試,在正常運行了兩天後,業務系統報錯:The connection pool has been exhausted, either raise MaxPoolSize (currently 800) or Timeout (curren ...
  • 背景 我們有些工具在 Web 版中已經有了很好的實踐,而在 WPF 中重新開發也是一種費時費力的操作,那麼直接集成則是最省事省力的方法了。 思路解釋 為什麼要使用 WPF?莫問為什麼,老 C# 開發的堅持,另外因為 Windows 上已經裝了 Webview2/edge 整體打包比 electron ...
  • EDP是一套集組織架構,許可權框架【功能許可權,操作許可權,數據訪問許可權,WebApi許可權】,自動化日誌,動態Interface,WebApi管理等基礎功能於一體的,基於.net的企業應用開發框架。通過友好的編碼方式實現數據行、列許可權的管控。 ...
  • .Net8.0 Blazor Hybird 桌面端 (WPF/Winform) 實測可以完整運行在 win7sp1/win10/win11. 如果用其他工具打包,還可以運行在mac/linux下, 傳送門BlazorHybrid 發佈為無依賴包方式 安裝 WebView2Runtime 1.57 M ...