06-Web后端基礎(java操作數據庫)

1. 前言

在前面我們學習MySQL數據庫時,都是利用圖形化客戶端工具(如:idea、datagrip),來操作數據庫的。

我們做為后端程序開發人員,通常會使用Java程序來完成對數據庫的操作。Java程序操作數據庫的技術呢,有很多啊,而最為底層、最為基礎的就是JDBC。

JDBC:(Java DataBase Connectivity),就是使用Java語言操作關系型數據庫的一套API。 【是操作數據庫最為基礎、底層的技術】

但是使用JDBC來操作數據庫,會比較繁瑣,所以現在在企業項目開發中呢,一般都會使用基于JDBC的封裝的高級框架,比如:Mybatis、MybatisPlus、Hibernate、SpringDataJPA。

而這些技術,目前的市場占有份額如下圖所示:

從上圖中,我們也可以看到,目前最為主流的就是Mybatis,其次是MybatisPlus。

所以,在我們的課程體系中呢,這兩種主流的操作數據庫的框架我們都要學習。 而我們在學習這兩個主流的框架之前,還需要學習一下操作數據庫的基礎基礎 JDBC。 然后接下來,再來學習Mybatis。 而在我們后面的課程中,我們還要學習MybatisPlus框架。 那么今天呢,我們就先來學習 JDBC 和 Mybatis。

今天課程安排:

  1. JDBC
  2. Mybatis
  3. SpringBoot配置文件

2. JDBC

2.1 介紹

JDBC:(Java DataBase Connectivity),就是使用Java語言操作關系型數據庫的一套API。

本質:

  • sun公司官方定義的一套操作所有關系型數據庫的規范,即接口。
  • 各個數據庫廠商去實現這套接口,提供數據庫驅動jar包。
  • 我們可以使用這套接口(JDBC)編程,真正執行的代碼是驅動jar包中的實現類。

那有了JDBC之后,我們就可以直接在java代碼中來操作數據庫了,只需要編寫這樣一段java代碼,就可以來操作數據庫中的數據。 示例代碼如下:

2.2 查詢數據

2.2.1 需求

需求:基于JDBC實現用戶登錄功能。

本質:其本質呢,其實就是基于JDBC程序,執行如下select語句,并將查詢的結果輸出到控制臺。SQL語句:

select * from user where username = 'linchong' and password = '123456';
2.2.2 準備工作

1). 創建一個maven項目

2). 創建一個數據庫 web,并在該數據庫中創建user表

create table user(id int unsigned primary key auto_increment comment 'ID,主鍵',username varchar(20) comment '用戶名',password varchar(32) comment '密碼',name varchar(10) comment '姓名',age tinyint unsigned comment '年齡'
) comment '用戶表';insert into user(id, username, password, name, age) values (1, 'daqiao', '123456', '大喬', 22),(2, 'xiaoqiao', '123456', '小喬', 18),(3, 'diaochan', '123456', '貂蟬', 24),(4, 'lvbu', '123456', '呂布', 28),(5, 'zhaoyun', '12345678', '趙云', 27);
2.2.3 代碼實現

AI提示詞(prompt):

你是一名java開發工程師,幫我基于JDBC程序來操作數據庫,執行如下SQL語句:

select * from user where username = 'daqiao' and password = '123456'

具體的代碼為:

1). 在 pom.xml 文件中引入依賴

<dependencies><!-- MySQL JDBC driver --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.30</version></dependency><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter</artifactId><version>5.9.3</version><scope>test</scope></dependency>
</dependencies>

2). 在 src/main/test/java 目錄下編寫測試類,定義測試方法

public class JDBCTest {/*** 編寫JDBC程序, 查詢數據*/@Testpublic void testJdbc() throws Exception {// 獲取連接Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/web", "root", "1234");// 創建預編譯的PreparedStatement對象PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM user WHERE username = ? AND password = ?");// 設置參數pstmt.setString(1, "daqiao"); // 第一個問號對應的參數pstmt.setString(2, "123456"); // 第二個問號對應的參數// 執行查詢ResultSet rs = pstmt.executeQuery();// 處理結果集while (rs.next()) {int id = rs.getInt("id");String uName = rs.getString("username");String pwd = rs.getString("password");String name = rs.getString("name");int age = rs.getInt("age");System.out.println("ID: " + id + ", Username: " + uName + ", Password: " + pwd + ", Name: " + name + ", Age: " + age);}// 關閉資源rs.close();pstmt.close();conn.close();}}

而上述的單元測試中,我們在SQL語句中,將將 用戶名 和密碼的值都寫死了,而這兩個值應該是動態的,是將來頁面傳遞到服務端的。 那么,我們可以基于前面所講解的JUnit中的參數化測試進行單元測試,代碼改造如下:

版本1:

@Test
public void testSelect() throws Exception {Connection connection = null;PreparedStatement preparedStatement = null;ResultSet resultSet = null;try {String url = "jdbc:mysql://localhost:3306/web01";String username = "root";String password = "fu921400521";Class.forName("com.mysql.cj.jdbc.Driver");connection = DriverManager.getConnection(url, username, password);preparedStatement = connection.prepareStatement("select * from user where username = ? and password = ?");preparedStatement.setString(1, "daqiao");preparedStatement.setString(2, "123456");resultSet = preparedStatement.executeQuery();while (resultSet.next()) {User user = new User(resultSet.getInt("id"),resultSet.getString("username"),resultSet.getString("password"),resultSet.getString("name"),resultSet.getInt("age"));System.out.println(user);}} catch (SQLException se) {se.printStackTrace();} catch (Exception e) {e.printStackTrace();}finally {try {if (resultSet != null) resultSet.close();if (preparedStatement != null) preparedStatement.close();if (connection != null) connection.close();}catch (SQLException se) {se.printStackTrace();}}}

版本2:

public class JDBCTest {/*** 編寫JDBC程序, 查詢數據*/@ParameterizedTest@CsvSource({"daqiao,123456"})public void testJdbc(String _username, String _password) throws Exception {// 獲取連接Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/web", "root", "1234");// 創建預編譯的PreparedStatement對象PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM user WHERE username = ? AND password = ?");// 設置參數pstmt.setString(1, _username); // 第一個問號對應的參數pstmt.setString(2, _password); // 第二個問號對應的參數// 執行查詢ResultSet rs = pstmt.executeQuery();// 處理結果集while (rs.next()) {int id = rs.getInt("id");String uName = rs.getString("username");String pwd = rs.getString("password");String name = rs.getString("name");int age = rs.getInt("age");System.out.println("ID: " + id + ", Username: " + uName + ", Password: " + pwd + ", Name: " + name + ", Age: " + age);}// 關閉資源rs.close();pstmt.close();conn.close();}}

如果在測試時,需要傳遞一組參數,可以使用 @CsvSource 注解。

2.2.4 代碼剖析

2.2.4.1 ResultSet

ResultSet(結果集對象):封裝了DQL查詢語句查詢的結果。

  • next():將光標從當前位置向前移動一行,并判斷當前行是否為有效行,返回值為boolean。
    • true:有效行,當前行有數據
    • false:無效行,當前行沒有數據
  • getXxx(…):獲取數據,可以根據列的編號獲取,也可以根據列名獲取(推薦)。

結果解析步驟:

2.2.4.2 預編譯SQL

其實我們在編寫SQL語句的時候,有兩種風格:

  • 靜態SQL(參數硬編碼)
conn.prepareStatement("SELECT * FROM user WHERE username = 'daqiao' AND password = '123456'");
ResultSet resultSet = pstmt.executeQuery();

這種呢,就是參數值,直接拼接在SQL語句中,參數值是寫死的。

  • 預編譯SQL(參數動態傳遞)
conn.prepareStatement("SELECT * FROM user WHERE username = ? AND password = ?");
pstmt.setString(1, "daqiao");
pstmt.setString(2, "123456");
ResultSet resultSet = pstmt.executeQuery();

這種呢,并未將參數值在SQL語句中寫死,而是使用 ? 進行占位,然后再指定每一個占位符對應的值是多少,而最終在執行SQL語句的時候,程序會將SQL語句(SELECT * FROM user WHERE username = ? AND password = ?),以及參數值("daqiao", "123456")都發送給數據庫,然后在執行的時候,會使用參數值,將?占位符替換掉。

那這種預編譯的SQL,也是在項目開發中推薦使用的SQL語句。主要的作用有兩個:

  • 防止SQL注入
  • 性能更高

那接下來,我們就來介紹一下這兩點。

2.2.4.2.1 SQL注入
  • SQL注入:通過控制輸入來修改事先定義好的SQL語句,以達到執行代碼對服務器進行攻擊的方法。

SQL注入最典型的場景,就是用戶登錄功能。

注入演示:

1). 打開課程資料中的文件夾 資料/02. SQL注入演示,運行其中的jar包 sql_Injection_demo-0.0.1-SNAPSHOT.jar,進入該目錄后,執行命令:

java -jar sql_Injection_demo-0.0.1-SNAPSHOT.jar

2). 打開瀏覽器訪問 http://localhost:9090/ ,必須登錄后才能訪問到系統。我們先測試正常的用戶名和密碼

3). 接下來,我們再來測試一下錯誤的用戶名和密碼 。

我們看到,如果用戶名密碼錯誤,是不能進入到系統中進行訪問的,會提示 用戶名和密碼錯誤

4). 那接下來,我們就要演示一下SQL注入現象,我們可以通過控制表單輸入,來修改事先定義好的SQL語句的含義。 從而來攻擊服務器。

點擊登錄后,我們看到居然可以成功進入到系統中。

為什么會出現這種現象呢?

在進行登錄操作時,怎么樣才算登錄成功呢? 如果我們查詢到了數據,就說明用戶名密碼是對的。 如果沒有查詢到數據,就說明用戶名或密碼錯誤。

而出現上述現象,原因就是因為,我們我們編寫的SQL語句是基于字符串進行拼接的 。 我們輸入的用戶名無所謂,比如:shfhsjfhja ,而密碼呢,就是我們精心設計的,如:' or '1' = '1

那最終拼接的SQL語句,如下所示:

我們知道,or 連接的條件,是或的關系,兩者滿足其一就可以。 所以,雖然用戶名密碼輸入錯誤,也是可以查詢返回結果的,而只要查詢到了數據,就說明用戶名和密碼是正確的。

2.2.4.2.2 SQL注入解決

而通過預編譯SQL(select * from user where username = ? and password = ?),就可以直接解決上述SQL注入的問題。 接下來,我們再來演示一下,通過預編譯SQL是否能夠解決SQL注入問題。

1). 打開課程資料中的文件夾 資料/02. SQL注入演示,運行其中的jar包 sql_prepared_demo-0.0.1-SNAPSHOT.jar,進入該目錄后,執行命令:

java -jar sql_prepared_demo-0.0.1-SNAPSHOT.jar

2). 打開瀏覽器訪問 http://localhost:9090/ ,必須登錄后才能訪問到系統 。我們先測試正常的用戶名和密碼

3). 那接下來,我們就要演示一下是否可以基于上述的密碼 ' or '1' = '1,來完成SQL注入 。

通過控制臺,可以看到輸入的SQL語句,是預編譯SQL語句。

而在預編譯SQL語句中,當我們執行的時候,會把整個' or '1'='1作為一個完整的參數,賦值給第2個問號(' or '1'='1進行了轉義,只當做字符串使用)

那么此時再查詢時,就查詢不到對應的數據了,登錄失敗。

注意:在以后的項目開發中,我們使用的基本全部都是預編譯SQL語句。

2.2.4.2.3 性能更高

2.3 增刪改數據

2.3.1 需求
  • 需求:基于JDBC程序,執行如下update語句。
  • SQL:
update user set password = '123456', gender = 2 where id = 1;
2.3.2 代碼實現

AI提示詞(prompt):

你是一名java開發工程師,幫我基于JDBC程序來操作數據庫,執行如下SQL語句:

update user set password = '123456', gender = 2 where id = 1;

代碼實現如下:

@ParameterizedTest
@CsvSource({"1,123456,25"})
public void testUpdate(int userId, String newPassword, int newAge) throws Exception {// 建立數據庫連接Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/web", "root", "1234");// SQL 更新語句String sql = "UPDATE user SET password = ?, age = ? WHERE id = ?";// 創建預編譯的PreparedStatement對象PreparedStatement pstmt = conn.prepareStatement(sql);// 設置參數pstmt.setString(1, newPassword); // 第一個問號對應的參數pstmt.setInt(2, newAge);      // 第二個問號對應的參數pstmt.setInt(3, userId);         // 第三個問號對應的參數// 執行更新int rowsUpdated = pstmt.executeUpdate();// 輸出結果System.out.println(rowsUpdated + " row(s) updated.");// 關閉資源pstmt.close();conn.close();
}
  • JDBC程序執行DML語句:int rowsUpdated = pstmt.executeUpdate(); //返回值是影響的記錄數
  • JDBC程序執行DQL語句:ResultSet resultSet = pstmt.executeQuery(); //返回值是查詢結果集

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/84472.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/84472.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/84472.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

uni-app學習筆記十三-vue3中slot插槽的使用

在頁面開發中&#xff0c;通常一個頁面分為頭部&#xff0c;尾部&#xff0c;和中心內容區。其中頭部&#xff0c;尾部一般比較固定&#xff0c;而中心區域往往是多樣的&#xff0c;需要自定義開發。此時&#xff0c;我們可以引入slot(插槽)來實現這一目標。<slot> 作為一…

Agent模型微調

這篇文章講解&#xff1a; 把 Agent 和 Fine-Tuning 的知識串起來&#xff0c;在更高的技術視角看大模型應用&#xff1b;加深對 Agent 工作原理的理解&#xff1b;加深對 Fine-Tuning 訓練數據處理的理解。 1. 認識大模型 Agent 1.1 大模型 Agent 的應用場景 揭秘Agent核心…

【最新版】Arduino IDE的安裝入門Demo

1、背景說明 1、本教程編寫日期為2025-5-24 2、Arduino IDE的版本為&#xff1a;Arduino IDE 2.3.6 3、使用的Arduino為Arduino Uno 1、ArduinoIDE的安裝 1、下載。網址如下&#xff1a;官網 2、然后一路安裝即可。 期間會默認安裝相關驅動&#xff0c;默認安裝即可。 3、安…

Python應用運算符初解

大家好!運算符是編程中不可或缺的工具&#xff0c;它們能幫助我們執行各種計算和操作。無論是數學運算&#xff0c;還是變量賦值&#xff0c;運算符都在背后默默發揮作用。對于編程初學者來說&#xff0c;理解并掌握常見運算符的用法是邁向編程世界的重要一步。 算術運算符: 加…

小米2025年校招筆試真題手撕(二)

一、題目 給一個長度為n的序列和一個整數x&#xff0c;每次操作可以選擇序列中的一個元素&#xff0c;將其從序列中刪去&#xff0c;或者將其值加一。 問至少操作多少次&#xff0c;可以使操作后的序列&#xff08;可以為空&#xff09;中數字之和是x的倍數。 輸入描述&#…

CNN卷積神經網絡到底卷了啥?

參考視頻&#xff1a;卷積神經網絡&#xff08;CNN&#xff09;到底卷了啥&#xff1f;8分鐘帶你快速了解&#xff01; 我們知道&#xff1a; 圖片是由像素點構成&#xff0c;即最終的成像效果是由背后像素的顏色數值所決定 在Excel中&#xff1a;有這樣一個由數值0和1組成的66…

教師技術知識對人工智能賦能下教學效果的影響:以教學創新為中介的實證研究

教師技術知識對人工智能賦能下教學效果的影響&#xff1a;以教學創新為中介的實證研究 摘要 隨著教育信息化的快速發展&#xff0c;人工智能技術在教育領域的應用日益廣泛&#xff0c;為教育教學帶來了深刻變革。然而&#xff0c;當前關于教師技術知識如何影響人工智能賦能下的…

Linux驅動學習筆記(九)

設備模型 1.kobject的全稱為kernel object&#xff0c;即內核對象&#xff0c;每一個kobject都會對應到系統/sys/下的一個目錄&#xff0c;這些目錄的子目錄也是一個kobject&#xff0c;以此類推&#xff0c;這些kobject構成樹狀關系&#xff0c;如下圖&#xff1a; kobject定…

25年上半年五月之軟考之設計模式

目錄 一、單例模式 二、工廠模式 三、 抽象工廠模式 四、適配器模式 五、策略模式 六、裝飾器模式 ?編輯 考點&#xff1a;會挖空super(coffeOpertion); 七、代理模式 為什么必須要使用代理對象&#xff1f; 和裝飾器模式的區別 八、備忘錄模式 一、單例模式 這個…

Python打卡第36天

浙大疏錦行 作業&#xff1a; 對之前的信貸項目&#xff0c;利用神經網絡訓練下&#xff0c;嘗試用到目前的知識點讓代碼更加規范和美觀。 import torch import torch.nn as nn import torch.optim as optim from sklearn.model_selection import train_test_split from sklear…

全面理解類和對象(下)

文章目錄 再談構造函數初始化列表 static概念&#xff1a; 友元友元函數友元類 內部類再次理解類和對象 再談構造函數 class Date { public:Date(int year, int month, int day){_year year;_month month;_day day;} private:int _year;int _month;int _day; };上述代碼有了…

TomatoSCI分析日記——層次聚類

TomatoSCI分析日記——層次聚類 今天介紹的是一種常見的聚類方法——層次聚類。層次聚類會將數據集劃分成嵌套的簇&#xff0c;形成一個層次結構&#xff08;樹狀圖&#xff09;&#xff0c;經常用于探究樣本的相似性。用大白話來說&#xff0c;就是&#xff1a;我有一大堆樣品…

mysql都有哪些鎖?

MySQL中的鎖機制是確保數據庫并發操作正確性和一致性的重要組成部分&#xff0c;根據鎖的粒度、用途和特性&#xff0c;可以分為多種類型。以下是MySQL中常見的鎖及其詳細說明&#xff1a; 一、按鎖的粒度劃分 行級鎖&#xff08;Row-level Locks&#xff09; 描述&#xff1a;…

flutter 項目調試、flutter run --debug調試模式 devtools界面說明

Flutter DevTools 網頁界面說明 1. 頂部導航欄 Inspector&#xff1a;查看和調試 Widget 樹&#xff0c;實時定位 UI 問題。Performance-- 性能分析面板&#xff0c;查看幀率、CPU 和 GPU 使用情況&#xff0c;識別卡頓和性能瓶頸。Memory-- 內存使用和對象分配分析&#xff…

使用Kotlin創建Spring Boot用戶應用項目

項目初始化與配置 通過Spring Initializr創建Kotlin項目 若需使用Kotlin語言開發Spring Boot應用(假設已安裝Kotlin環境),可通過start.spring.io進行項目初始化。在項目創建頁面需進行以下關鍵配置: 語言選擇:切換至Kotlin選項項目元數據:需填寫Group(如com.apress.us…

【Linux網絡篇】:Socket網絡套接字以及簡單的UDP網絡程序編寫

?感謝您閱讀本篇文章&#xff0c;文章內容是個人學習筆記的整理&#xff0c;如果哪里有誤的話還請您指正噢? ? 個人主頁&#xff1a;余輝zmh–CSDN博客 ? 文章所屬專欄&#xff1a;Linux篇–CSDN博客 文章目錄 網絡編程套接字一.預備知識1.理解源IP地址和目的IP地址2.認識端…

Python爬蟲實戰:研究Newspaper框架相關技術

1. 引言 1.1 研究背景與意義 互聯網的快速發展使得新聞信息呈現爆炸式增長&#xff0c;如何高效地獲取和分析這些新聞數據成為研究熱點。新聞爬蟲作為一種自動獲取網頁內容的技術工具&#xff0c;能夠幫助用戶從海量的互聯網信息中提取有價值的新聞內容。本文基于 Python 的 …

【node.js】實戰項目

個人主頁&#xff1a;Guiat 歸屬專欄&#xff1a;node.js 文章目錄 1. 項目概覽與架構設計1.1 實戰項目&#xff1a;企業級電商管理系統1.2 技術棧選擇 2. 項目初始化與基礎架構2.1 項目結構設計2.2 基礎配置管理 3. 用戶服務實現3.1 用戶服務架構3.2 用戶模型設計3.3 用戶服務…

Mybatis框架的構建(IDEA)

選擇maven項目 修改設置 在設置中添加自定義代碼模板 開始寫代碼 動態SQL語句的示例&#xff1a; pom文件&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"…

經濟法-6-公司法律制度知識點

一、出資期限 1.有限責任公司&#xff1a;全體股東需在公司成立之日起5年內繳足認繳的注冊資本 2.股份有限公司&#xff1a;以發起方式設立的&#xff0c;發起人需在公司登記前實繳全部股款 3.認繳期加速到期 公司不能清償到期債務的&#xff0c;公司或者已到期債權的債權人…