日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

JDBC小记

發布時間:2025/3/12 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JDBC小记 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

JDBC小記

前言

昨天剛沖完了jdbc,今天來總結

一.JDBC介紹

JDBC (百度百科): Java數據庫連接,(Java Database Connectivity,簡稱JDBC)是Java語言中用來規范客戶端程序如何來訪問數據庫的應用程序接口,提供了諸如查詢和更新數據庫中數據的方法。JDBC也是Sun Microsystems的商標。我們通常說的JDBC是面向關系型數據庫的。

說白了 JDBC就是Java數據庫連接,就是用Java語言來操作數據庫。原來我們操作數據庫是在控制臺使用SQL語句來操作數據庫,JDBC是用Java語言向數據庫發送SQL語句.

二.JDBC原理圖

三.JDBC的本質:

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

JDBC到底是什么

SUN公司制定的一套接口(interface),(在java.sql.*;包下有很多接口)

目的:解耦合——>降低程序的耦合度,提高程序的擴展力


**附:**java鏈接MySQL驅動包最新版下載地址:https://dev.mysql.com/downloads/connector/j/,解壓后得到jar庫文件,然后在項目中導入該庫文件.

博主使用的版本是mysql-connector-java-5.1.47.jar

四.什么是驅動

驅動,是指驅動計算機里軟件的程序。驅動程序全稱設備驅動程序,是添加到操作系統中的特殊程序,其中包含有關硬件設備的信息。此信息能夠使計算機與相應的設備進行通信。驅動程序是硬件廠商根據操作系統編寫的配置文件,可以說沒有驅動程序,計算機中的硬件就無法工作。

例如:網卡,聲卡,顯卡等等 必須要安裝驅動程序,不然這些硬件就無法正常工作。

五.為什么要面向接口編程?

解耦合:降低程序的耦合度,提高程序的擴展力
多態機制就是非常典型的:面向抽象編程(不要面向具體編程)

Animal a = new Cat(); Animal a = new Dog(); //喂養的方法 public void feed(Animal a ){ //面向父類型編程} 不建議: Dog d = new Dog(); Cat c = new Cat();

思考:為什么sun公司要制定一套JDBC接口呢?
因為每個數據庫的實現原理不一樣,oracle、mysql、ms sqlserver都有自己的原理,每個數據庫產品都有自己獨特的實現原理.

六.JDBC核心類(接口)介紹

JDBC中的核心類有:DriverManager、Connection、Statement,和ResultSet

DriverManger(驅動管理器)的作用有兩個:

  • 注冊驅動:這可以讓JDBC知道要使用的是哪個驅動;

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

  • 獲取Connection:如果可以獲取到Connection,那么說明已經與數據庫連接上了。

    DriverManager.getConnection(url,username,password)

Connection對象表示連接,與數據庫的通訊都是通過這個對象展開的:

  • Connection最為重要的一個方法就是用來獲取Statement對象;

    Statement stmt = con.createStatement();

  • Statement是用來向數據庫發送SQL語句的,這樣數據庫就會執行發送過來的SQL語句

  • void executeUpdate(String sql):執行更新操作(insert、update、delete等);

  • ResultSet executeQuery(String sql):執行查詢操作,數據庫在執行查詢后會把查詢結果,查詢結果就是ResultSet;

ResultSet對象表示查詢結果集,只有在執行查詢操作后才會有結果集的產生。結果集是一個二維的表格,有行有列。操作結果集要學習移動ResultSet內部的“行光標”,以及獲取當前行上的每一列上的數據:

  • boolean next():使“行光標”移動到下一行,并返回移動后的行是否存在;

    rs.next();//光標移動到第一行 rs.getInt(1);//獲取第一行第一列的數據
  • XXX getXXX(int col):獲取當前行指定列上的值,參數就是列數,列數從1開始,而不是0。

    //常用的方法 Object getObject(int col) String getString(int col) int getInt(int col) double getDouble(int col)

七.JDBC編程6步(超級重要,需要背會!!!)

第1步:注冊驅動 (只做一次)

第2步:獲取數據庫連接對象(Connection)

第3步:獲取數據庫操作對象(Statement)

第4步:執行sql語句(增刪改查)

第5步:處理查詢結果集(ResultSet)

第6步:釋放資源


第1步:注冊驅動 (只做一次)

作用:告訴java程序,即將要連接的是哪個牌子的數據庫.

注冊驅動的兩種方法 (例如,注冊MySQL的數據庫驅動) :

// 第一種: 推薦 Class.forName(com.mysql.jdbc.Driver);

Class.forName是把這個類加載到JVM中,加載的時候,就會執行其中的靜態初始化塊,完成驅動的初始化的相關工作。


// 第二種: 不推薦 DriverManager.registerDriver(new com.mysql.jdbc.Driver()); // DriverManager類的registerDriver()方法的參數是java.sql.Driver,但java.sql.Driver是一個接口,實現類由mysql驅動來提供,mysql驅動中的java.sql.Driver接口的實現類為com.mysql.jdbc.Driver

上面代碼雖然可以注冊驅動,但是出現硬編碼(代碼依賴mysql驅動jar包),如果將來想連接Oracle數據庫,那么必須要修改代碼的。并且其實這種注冊驅動的方式是注冊了兩次驅動!


通過初始化驅動類com.mysql.jdbc.Driver,該類就在 mysql-connector-java-5.0.8-bin.jar中。如果你使用的是oracle數據庫那么該驅動類將不同。

**注意:**Class.forName需要捕獲ClassNotFoundException.

try {Class.forName("com.mysql.jdbc.Driver"); } catch (ClassNotFoundException e) { e.printStackTrace();}

第2步:獲取數據庫連接對象(Connection)

表示jvm的進程和數據庫進程之間的通道打開了,這屬于進程之間的通信,重量級的,使用完一定要關閉

可以使用 DriverManager.getConnection()方法建立連接。根據傳入參數的不同,有三種重載的DriverManager.getConnection()方法:

  • getConnection(String url)
  • getConnection(String url, Properties prop)
  • getConnection(String url, String user, String password)

還可以在url中提供參數

jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=UTF8

useUnicode參數指定這個連接數據庫的過程中,使用的字節集是Unicode字節集;

characherEncoding參數指定穿上連接數據庫的過程中,使用的字節集編碼為UTF-8編碼。請注意,mysql中指定UTF-8編碼是給出的是UTF8,而不是UTF-8。

這里每個格式都需要一個數據庫URL。 數據庫**URL是指向數據庫的地址。**制定數據庫URL是建立連接相關聯的大多數錯誤問題發生的地方。各數據庫對應的URL如下所示:

假設我們現在需要連接MySQL數據庫,格式為:jdbc:mysql://hostname:port/datebaseName。我們需要的信息是hostname主機名和端口號,一般默認為localHost:3306;還需要datebaseName數據庫名,假設為mydb;當然還有URL格式未包含的也是必須的信息:連接數據庫的用戶名和密碼,假設為root和123456。那么就有URL:

  • 1 String url = "jdbc:mysql//localhost:3306/mydb";

下面分別使用四種方法來實現:

  • 使用一個URL作為參數的方式:需要將username+password以參數的形式放到URL中,但是每種數據庫的放置都不太相同

    //連接mysql的純URL String url = "jdbc:mysql//localhost:3306/mydb?username=root&password=123456"; Connection conn = DriverManager.getConnection(url,p); //連接Oracle的純URL String url = "jdbc:oracle:thin:root/123456@192.0.0.10:1521:mydb";Connection conn = DriverManager.getConnection(url);
  • 使用URL、properties作為參數的方式:即需要將username和password以鍵值對形式存放在properties對象中作為參數

    //MySql String url = "jdbc:mysql//localhost:3306/mydb"; Properties p = new Properties(); p.put("username","root"); p.put("password","123456"); Connection conn = DriverManager.getConnection(url,p);
  • 使用URL、username、password三個參數分開的方式(推薦

    String url = "jdbc:mysql//localhost:3306/mydb"; String username = "root"; String password = "123456"; Connection conn = DriverManager.getConnection(url,username,password);
  • 利用java.sql.Drivermanager類中的getConnection()方法與數據庫建立連接。

Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mydb?characterEncoding=UTF-8", "root", "123456");// 說明: // DriverManager.getConnection(“jdbc:mysql://數據庫地址:端口號/數據庫名”,”用戶名”, “密碼”); // 數據庫服務端的IP地址:127.0.0.1 (這是本機,如果連接其他電腦上的數據庫,需填寫相應的IP地址) // 數據庫的端口號: 3306 (mysql專用端口號) // 數據庫名稱 mydb(根據你自己數據庫中的名稱填寫) // 編碼方式 UTF-8 // 賬號 root // 密碼 123456(如果你在創建數據庫的時候沒有使用默認的賬號和密碼,請填寫自己設置的賬號和密碼)

注意: Connection是與特定數據庫連接回話的接口,使用的時候需要導包,而且必須在程序結束的時候將其關閉。getConnection方法也需要捕獲SQLException異常。

因為在進行數據庫的增刪改查的時候都需要與數據庫建立連接,所以可以在項目中將建立連接寫成一個工具方法,用的時候直接調用即可:

/*** 取得數據庫的連接* @return 一個數據庫的連接*/ public static Connection getConnection(){Connection conn = null;try {//初始化驅動類com.mysql.jdbc.DriverClass.forName("com.mysql.jdbc.Driver");conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mydb?characterEncoding=UTF-8","root", "123456");//該類就在 mysql-connector-java-5.0.8-bin.jar中,如果忘記了第一個步驟的導包,就會拋出ClassNotFoundException} catch (ClassNotFoundException e) { e.printStackTrace();}catch (SQLException e) { e.printStackTrace();}return conn;}

第3步:獲取數據庫操作對象(Statement或者PreparedStatement)

SQL語句的執行對象按理說有Statement和PreparedStatement兩個,但我們一般都不會去使用Statement,先看下兩者的基本描述:

  • Statement 是 Java 執行數據庫操作的一個重要接口,用于在已經建立數據庫連接的基礎上,向數據庫發送要執行的SQL語句。Statement對象,用于執行不帶參數的簡單SQL語句,即靜態SQL語句。
  • PreparedStatement 繼承于Statement。實例包含已編譯的 SQL 語句,這就是使語句“準備好”。包含于 PreparedStatement 對象中的 SQL 語句可具有一個或多個 IN 參數。IN參數的值在 SQL 語句創建時未被指定。相反的,該語句為每個 IN 參數保留一個問號(“?”)作為占位符。每個問號的值必須在該語句執行之前,通過適當的setXXX() 方法來提供。

簡言之,Statement執行靜態SQL語句,而它的子類PreparedStatement執行預編譯SQL,即可傳入參數。兩者相比之下,PreparedStatement有以下優勢

  • **預編譯處理,可動態執行SQL語句。**很明顯,SQL語句的預編譯,使用占位符?去代替未知數據,因而一個句子可以執行多種不同的SQL,而Statement需要重新書寫SQL語句,笨重。
  • 速度快,執行效率高。SQL語句會預編譯在數據庫系統中。執行計劃同樣會被緩存起來,它允許數據庫做參數化查詢。使用預處理語句比普通的查詢更快,因為它做的工作更少(數據庫對SQL語句的分析,編譯,優化已經在第一次查詢前完成了)。我們要利用預編譯的特性

(1). 利用java.sql.Connection創建用于執行SQL語句的Statement。

Statement stmt = connection.createStatement();

注意:使用Statement會引起sql注入問題,在實際開發中很少使用,用的的更多的是它的子類PreparedStatement

比如sql注入問題如下:

String sql = "SELECT * FROM users WHERE name = '" + userName + "' and pw = '"+ passWord +"';"

驗證需要用戶輸入用戶名和密碼,正確則執行查詢語句(登錄),但如果這樣輸入:

userName = "1' OR '1'='1"; passWord = "1' OR '1'='1";

那么執行語句就變成了:

1 String sql = "SELECT * FROM users WHERE name = '1' OR '1'='1' and pw = '1' OR '1'='1';"

這樣,where語句恒為真,就能實現無賬號登錄。此外便可能被惡意修改甚至刪除數據表。然而使用PreparedStatement的參數化的查詢可以阻止大部分的SQL注入。在使用參數化查詢的情況下,數據庫系統(eg:MySQL)不會將參數的內容視為SQL指令的一部分來處理,而是在數據庫完成SQL指令的編譯后,才套用參數運行,且占位符?不允許多值,只能填入一個值,因此就算參數中含有破壞性的指令,也不會被數據庫所運行。

(2) .使用Connection對象的PreparedStatement(sql)方法進行獲取:

String sql = "select * from user where name=? and ange=?";//預處理,需要我們先寫好sql語句 PreparedStatement ps = conn.preparedStatement(sql);//conn是連接對象,參數為sql語句

第4步:執行sql語句(增刪改查)

SQL語言共分為四大類:數據查詢語言DQL,數據操縱語言DML,數據定義語言DDL,數據控制語言DCL

sql語句有增刪查改等幾種類型,所以執行方法有以下三種:

  • execute():執行SQL語句,可以是任何種類的 SQL 語句。返回值是boolean類型。
  • executeQuery():執行SQL語句查詢,查詢結果返回為**ResultSet 對象**。
  • executeUpdate() :執行更新語句。該語句必須是一個 SQL 數據操作語言(Data Manipulation Language,DML)語句,比如 INSERT、UPDATE 或 DELETE 語句;或者是無返回內容的 SQL 語句,比如 DDL 語句。返回值是int。

例如本例中的語句是查詢語句,所以執行代碼為:

  • //執行查詢語句,并把結果集返回給集合ResultSet ResultSet rs = ps.executeQuery();

第5步:處理查詢結果集(ResultSet)

如果返回值是boolean或者int很好處理,但如果是查詢結果集ResultSet對象,一般使用while循環來處理:

ResultSet 對象具有指向其當前數據行的光標。最初,光標被置于第一行之前。next() 方法將光標移動到下一行;因為該方法在 ResultSet 對象沒有下一行時返回 false,所以可以在 while 循環中使用它來迭代結果集。另外,可以使用ResultSet對象的getXXX(int columnIndex)獲得游標所在行指定列的值。原理如下圖所示:

所以,本例的結果集處理如下:

1 while(rs.next()){ 2 system.out.println(rs.getString(1)); 3 system.out.println(rs.getInt(2)); 4 }

第6步:釋放資源

在JDBC程序結束之后,顯式地需要關閉與數據庫的所有連接以結束每個數據庫會話。 但是,如果在編寫程序中忘記了關閉也沒有關系,Java的垃圾收集器將在清除過時的對象時也會關閉這些連接。

依靠垃圾收集,特別是數據庫編程,是一個非常差的編程實踐。所以應該要使用與連接對象關聯的close()方法關閉連接。要確保連接已關閉,可以將關閉連接的代碼中編寫在“finally”塊中。 一個finally塊總是會被執行,不管是否發生異常。

conn.close();

八.JDBCUtils工具類

因為傳統JDBC的開發,注冊驅動,獲得連接,釋放資源這些代碼都是重復編寫的。所以可以將重復的代碼提取到一個類中來完成

import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; /*** JDBC的工具類* @author CodeAnime**/ public class JDBCUtils {private static final String driverClassName;private static final String url;private static final String username;private static final String password;static{driverClassName="com.mysql.jdbc.Driver";url="jdbc:mysql:///web_test3";username="root";password="123456";}/*** 注冊驅動的方法*/public static void loadDriver(){try {Class.forName(driverClassName);} catch (ClassNotFoundException e) {e.printStackTrace();}}/*** 獲得連接的方法*/public static Connection getConnection(){Connection conn = null;try{// 將驅動一并注冊:loadDriver();// 獲得連接conn = DriverManager.getConnection(url,username, password);}catch(Exception e){e.printStackTrace();}return conn;}/*** 釋放資源的方法*/public static void release(Statement stmt,Connection conn){if(stmt != null){try {stmt.close();} catch (SQLException e) {e.printStackTrace();}stmt = null;}if(conn != null){try {conn.close();} catch (SQLException e) {e.printStackTrace();}conn = null;}}public static void release(ResultSet rs,Statement stmt,Connection conn){// 資源釋放:if(rs != null){try {rs.close();} catch (SQLException e) {e.printStackTrace();}rs = null;}if(stmt != null){try {stmt.close();} catch (SQLException e) {e.printStackTrace();}stmt = null;}if(conn != null){try {conn.close();} catch (SQLException e) {e.printStackTrace();}conn = null;}} }

測試案例:導入工具類,查詢用戶信息

import java.sql.Connection; import java.sql.ResultSet; import java.sql.Statement; import org.junit.Test; import com.xdr630.jdbc.utils.JDBCUtils;/*** JDBC工具類的測試* @author xdr**/ public class JDBCDemo3 {@Test/*** 查詢操作:使用工具類*/public void demo1(){Connection conn = null;Statement stmt = null;ResultSet rs = null;try{// 獲得連接:conn = JDBCUtils.getConnection();// 創建執行SQL語句的對象:stmt = conn.createStatement();// 編寫SQL:String sql = "select * from user";// 執行查詢:rs = stmt.executeQuery(sql);// 遍歷結果集:while(rs.next()){System.out.println(rs.getInt("id")+" "+rs.getString("username")+" "+rs.getString("password"));}}catch(Exception e){e.printStackTrace();}finally{// 釋放資源:JDBCUtils.release(rs, stmt, conn);}} }

另一種寫法:

jdbc.properties屬性文件

注意:屬性配置文件必須以properties結尾,且存儲在src源目錄下

driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/mydb user=root password=123456

JDBCUtils.java工具類

public class JDBCUtil(){//類文件屬性,可以在類文件所有的方法中使用private Connection conn = null; private PreparedStatement ps = null;/*** 在當前類文件第一次被加載到JVM時,JVM將會自動調用當前類文件靜態語句塊*/static {//1. 注冊數據庫服務器提供的Driver接口實現類try{ResourceBundle bundle = ResourceBundle.getBundle("jdbc");String driver = bundle.getString("driver");Class.forName(driver);}catch(ClassNotFoundException e){e.printStackTrace();}}/*** 封裝Connection對象創建細節* @return 數據庫連接的對象*///這里我們選擇拋出異常,而不是自行內部處理。是讓調用此方法的人知道出現異常時的控制臺出現的異常信息public Connection creatConnection() throws SQLException {//采用資源綁定器來綁定屬性配置文件ResourceBundle bundle = ResourceBundle.getBundle("jdbc");String url = bundle.getString("url");String username = bundle.getString("username");String password = bundle.getString("password");//2. 創建一個連接通道交給Connection接口的實例對象[Connection]管理conn = DriverManager.getConnection(url,username,password);return conn;}/*** 封裝PreparedStatement對象創建細節* @param sql sql語句* @return */public PreparedStatement createStatement(String sql) throws SQLException {Connection conn = creatConnection();//3. 創建一個交通工具交給 PreparedStatement 接口的實例對象[PreparedStatement]管理ps = conn.prepareStatement(sql);//4. 由交通工具在Java工程與數據庫服務器之間進行傳輸,推送SQL命令并帶回執行結果return ps;}/*** 封裝PreparedStatement與Connection對象銷毀細節*/public void close(){if (ps != null){try {ps.close();} catch (SQLException e) {e.printStackTrace();}}if (conn != null) {try {conn.close();} catch (SQLException e) {e.printStackTrace();}}}/*** 封裝PreparedStatement與Connection與ResultSet對象銷毀細節* @param rs 查詢結果集*/public void close(ResultSet rs){if (rs != null) {try {rs.close();} catch (SQLException e) {e.printStackTrace();}}close();} }

JDBCTest01.java測試

public class JDBCTest01 {public static void main(String[] args) {//創建JDBC工具類對象JdbcUtil util = new JdbcUtil();PreparedStatement ps = null;ResultSet rs = null;try {String sql = "select * from studnet where studentid = ?";//這里由于在工具類中是拋出異常的,那么在調用時再拋出異常給JVM虛擬機就顯然不太合理了,此時我們選擇try...catch...內部處理ps = util.createStatement(sql);ps.setString(5,"田七");rs = ps.executeQuery();while (rs.next()){System.out.println(rs.getInt("studentid") + rs.getString("studnetname"));}} catch (SQLException e) {e.printStackTrace();}finally {//在finally語句塊中的語句必定執行util.close(rs);}} }

參考文章:

  • 作者 : Jungle_Rao

    • 鏈接:https://blog.csdn.net/Jungle_Rao/article/details/81274720
  • 作者 : Qiao_Zhi

    • https://www.cnblogs.com/qlqwjy/p/8227665.html
  • 作者 : 叫我玉弟大人

    • https://www.cnblogs.com/jwyddr/p/11661096.html
  • 作者 : 風大

    • https://www.cnblogs.com/fzz9/p/8970210.html
  • 作者 : newwaylau

    • https://zhuanlan.zhihu.com/p/114709445

總結

以上是生活随笔為你收集整理的JDBC小记的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。