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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

JDBC技术详解

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

文章目錄

  • 1 綜述
  • 2 JDBC相關概念
    • 2.1 什么是JDBC
    • 2.2 JDBC有什么用
    • 2.3 數據庫驅動
    • 2.4 JDBC架構
      • 2.4.1 雙層結構
      • 2.4.2 三層架構
  • 3 JDBC常用接口
    • 3.1 Driver接口
    • 3.2 Connection接口
    • 3.3 Statement接口
    • 3.4 ResultSet接口
  • 4 JDBC使用方法
    • 4.1 下載jar包
    • 4.2 導入jar包
    • 4.3 JDBC使用步驟
    • 4.4 使用代碼示例
      • 4.4.1 插入更新操作
  • 5 封裝提取工具類
  • 6 SQL注入
    • 6.1 sql注入演示
    • 6.2 PreparedStatement使用示例
  • 7 JDBC操縱事務
  • 8 批處理

1 綜述

本文檔主要對JDBC進行詳細說明,包括JDBC的相關概念、架構說明、工作原理、常用接口以及具體的使用方法等。

2 JDBC相關概念

2.1 什么是JDBC

JDBC英文名為:Java Data Base Connectivity(Java數據庫連接)

官方解釋它是Java編程語言和廣泛的數據庫之間獨立于數據庫的連接標準的Java API,根本上說JDBC是一種規范,它提供的接口,一套完整的,允許便捷式訪問底層數據庫。可以用JAVA來寫不同類型的可執行文件:JAVA應用程序、JAVA Applets、Java Servlet、JSP等,不同的可執行文件都能通過JDBC訪問數據庫,又兼備存儲的優勢。簡單說它就是JAVA與數據庫的連接的橋梁或者插件,用JAVA代碼就能操作數據庫的增刪改查、存儲過程、事務等。

2.2 JDBC有什么用

我們用JAVA就能連接到數據庫;創建SQL或者MYSQL語句;執行SQL或MYSQL的查詢數據庫;查看和修改結果記錄。

2.3 數據庫驅動

我們安裝好數據庫之后,我們的應用程序也是不能直接使用數據庫的,必須要通過相應的數據庫驅動程序,通過驅動程序去和數據庫打交道。其實也就是數據庫廠商的JDBC接口實現,即對Connection等接口的實現類的jar文件。

下載地址:https://mvnrepository.com/artifact/mysql/mysql-connector-java

2.4 JDBC架構

分為雙層架構和三層架構。

2.4.1 雙層結構

  • 作用:此架構中,Java Applet 或應用直接訪問數據源。
  • 條件:要求 Driver 能與訪問的數據庫交互。
  • 機制:用戶命令傳給數據庫或其他數據源,隨之結果被返回。
  • 部署:數據源可以在另一臺機器上,用戶通過網絡連接,稱為 C/S配置(可以是內聯網或互聯網)。

2.4.2 三層架構

3 JDBC常用接口

3.1 Driver接口

Driver接口由數據庫廠家提供,作為java開發人員,只需要使用Driver接口就可以了。在編程中要連接數據庫,必須先裝載特定廠商的數據庫驅動程序,不同的數據庫有不同的裝載方法。如:

  • 裝載MySql驅動:
Class.forName("com.mysql.jdbc.Driver");
  • 裝載Oracle驅動:
Class.forName("oracle.jdbc.driver.OracleDriver");

3.2 Connection接口

Connection與特定數據庫的連接,在連接上下文中執行sql語句并返回結果。DriverManager.getConnection(url, user, password)方法建立在JDBC URL中定義的數據庫Connection連接上。

  • 連接MySql數據庫:
Connection conn = DriverManager.getConnection("jdbc:mysql://host:port/database", "user", "password");
  • 連接Oracle數據庫:
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@host:port:database", "user", "password");
  • 連接SqlServer數據庫:
Connection conn = DriverManager.getConnection("jdbc:microsoft:sqlserver://host:port; DatabaseName=database", "user", "password");

常用方法:

  • createStatement():創建向數據庫發送sql的statement對象。
  • prepareStatement(sql) :創建向數據庫發送預編譯sql的PrepareSatement對象。
  • prepareCall(sql):創建執行存儲過程的callableStatement對象。
  • setAutoCommit(boolean autoCommit):設置事務是否自動提交。
  • commit() :在鏈接上提交事務。
  • rollback() :在此鏈接上回滾事務。

3.3 Statement接口

用于執行靜態SQL語句并返回它所生成結果的對象。

三種Statement類:

  • Statement:由createStatement創建,用于發送簡單的SQL語句(不帶參數)。
  • PreparedStatement :繼承自Statement接口,由preparedStatement創建,用于發送含有一個或多個參數的SQL語句。PreparedStatement對象比Statement對象的效率更高,并且可以防止SQL注入,所以我們一般都使用PreparedStatement。
  • CallableStatement:繼承自PreparedStatement接口,由方法prepareCall創建,用于調用存儲過程。
  • 常用Statement方法:

    • execute(String sql):運行語句,返回是否有結果集
    • executeQuery(String sql):運行select語句,返回ResultSet結果集。
    • executeUpdate(String sql):運行insert/update/delete操作,返回更新的行數。
    • addBatch(String sql) :把多條sql語句放到一個批處理中。
    • executeBatch():向數據庫發送一批sql語句執行。

    3.4 ResultSet接口

    ResultSet提供檢索不同類型字段的方法,常用的有:

    • getString(int index)、getString(String columnName):獲得在數據庫里是varchar、char等類型的數據對象。
    • getFloat(int index)、getFloat(String columnName):獲得在數據庫里是Float類型的數據對象。
    • getDate(int index)、getDate(String columnName):獲得在數據庫里是Date類型的數據。
    • getBoolean(int index)、getBoolean(String columnName):獲得在數據庫里是Boolean類型的數據。
    • getObject(int index)、getObject(String columnName):獲取在數據庫里任意類型的數據。
    • 等還有其他的獲取類型方法。

    ResultSet還提供了對結果集進行滾動的方法:

    • next():移動到下一行
    • Previous():移動到前一行
    • absolute(int row):移動到指定行
    • beforeFirst():移動resultSet的最前面。
    • afterLast():移動到resultSet的最后面。

    注意:使用后依次關閉對象及連接:ResultSet → Statement → Connection。

    4 JDBC使用方法

    4.1 下載jar包

    上面以及展示下載地址,下載合適的版本即可。

    4.2 導入jar包

  • 在項目下建立lib文件夾
  • 將jar包復制到文件夾中
  • 將文件夾添加為Library
  • 4.3 JDBC使用步驟

    使用JDBC的步驟:

  • 加載JDBC驅動程序
  • 構造數據庫鏈接信息
  • 建立數據庫連接Connection
  • 創建執行SQL的語句Statement對象
  • 使用Statement對象執行SQL
  • 處理執行結果ResultSet
  • 釋放資源
  • 4.4 使用代碼示例

    package com.wzh.demo01;import java.sql.*;public class JdbcDemo01 {public static void main(String[] args) throws ClassNotFoundException, SQLException {// 1 加載JDBC驅動程序Class.forName("com.mysql.jdbc.Driver");// 2 構造數據庫鏈接信息(以MySql為例)String url = "jdbc:mysql://localhost:3306/test_go?useUnicode=true&characterEncoding=utf8&useSSL=true";String username = "root";String pwd = "root";// 3 建立數據庫連接ConnectionConnection connection = DriverManager.getConnection(url, username, pwd);// 4 創建執行SQL的語句Statement對象Statement statement = connection.createStatement();// 5 使用Statement對象執行SQLString sql = "select * from user";ResultSet resultSet = statement.executeQuery(sql);// 6 處理執行結果ResultSetwhile (resultSet.next()) {System.out.println("id=" + resultSet.getObject("id"));System.out.println("name=" + resultSet.getObject("name"));System.out.println("birthday=" + resultSet.getObject("birthday"));}// 7 釋放資源 (注意關閉順序)resultSet.close();statement.close();connection.close();} }

    4.4.1 插入更新操作

    String sql = "insert into user(name,birthday) value ('hao','2021-06-28')"; int i = statement.executeUpdate(sql); if(i>0){System.out.println("插入數據成功"); }String sql1 = "update user set name='nn' where id = 2"; int i1 = statement.executeUpdate(sql1); if(i1 > 0){System.out.println("更新數據成功"); }

    5 封裝提取工具類

  • 在src目錄下新建db.properites用于保存數據庫配置信息;
  • driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/test_go?useUnicode=true&characterEncoding=utf8&useSSL=true username=root password=root
  • 新建utils包,再新建JdbcUtils.java文件,寫入如下代碼
  • package com.wzh.demo02.utils;import java.io.InputStream; import java.sql.*; import java.util.Properties;public class JdbcUtils {private static String driver = null;private static String url = null;private static String username = null;private static String password = null;static {try {InputStream is = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");Properties properties = new Properties();properties.load(is);driver = properties.getProperty("driver");url = properties.getProperty("url");username = properties.getProperty("username");password = properties.getProperty("password");// 1 驅動只用加載一次Class.forName(driver);} catch (Exception e) {e.printStackTrace();}}// 獲取鏈接public static Connection getConnection() throws SQLException {return DriverManager.getConnection(url, username, password);}// 釋放資源public static void release(Connection conn, Statement st, ResultSet rs) throws SQLException {if (rs != null) {rs.close();}if (st != null) {st.close();}if (conn != null) {conn.close();}} }
  • 后可在主函數使用
  • package com.wzh.demo02;import com.wzh.demo02.utils.JdbcUtils;import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement;public class Test {public static void main(String[] args) {Connection conn = null;Statement st = null;ResultSet rs = null;try {conn = JdbcUtils.getConnection();st = conn.createStatement();// 新增String sql_i = "insert into user(name,birthday) value ('張三','2021-06-28')";int i = st.executeUpdate(sql_i);if (i > 0) {System.out.println("插入成功");}// 修改String sql_u = "update user set name='李四' where id = 3";int i1 = st.executeUpdate(sql_u);if (i1 > 0) {System.out.println("更新數據成功");}// 刪除String sql_d = "delete from user where id = 3";int i2 = st.executeUpdate(sql_d);if (i2 > 0) {System.out.println("刪除成功");}// 查找String sql_q = "select * from user";rs = st.executeQuery(sql_q);while (rs.next()){System.out.println(rs.getString("name"));}} catch (Exception e) {e.printStackTrace();} finally {try {JdbcUtils.release(conn, st, rs);} catch (SQLException e) {e.printStackTrace();}}} }

    6 SQL注入

    詳細可觀看此篇博文:https://www.cnblogs.com/myseries/p/10821372.html

    6.1 sql注入演示

    package com.wzh.demo02;import com.wzh.demo02.utils.JdbcUtils;import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement;public class Sql注入 {public static void main(String[] args) {//正常使用//login("hao", "123456");// 此時為sql注入login(" 'or '1=1","123456");}public static void login(String username, String password) {Connection conn = null;Statement st = null;ResultSet rs = null;try {conn = JdbcUtils.getConnection();st = conn.createStatement();String sql_login = "select * from user where name='" + username + "' and password='" + password + "'";rs = st.executeQuery(sql_login);if (rs.next()) {System.out.println("登錄成功");}else{System.out.println("登錄失敗");}} catch (Exception e) {e.printStackTrace();} finally {try {JdbcUtils.release(conn, st, rs);} catch (SQLException e) {e.printStackTrace();}}}}

    由上可知Statement是不安全的,PreparedStatement可以防止SQL注入。效率更高。

    6.2 PreparedStatement使用示例

    package com.wzh.demo02;import com.wzh.demo02.utils.JdbcUtils;import java.sql.*;public class JdbcDemo03 {public static void main(String[] args) {Connection conn = null;PreparedStatement st = null;ResultSet rs = null;try {conn = JdbcUtils.getConnection();// 區別:先寫sql// 使用 ? 占位符代替參數String sql_i = "insert into user(name,birthday) value (?,?)";st = conn.prepareStatement(sql_i); // 預編譯sql,// 手動給參數賦值st.setString(1, "lisi");st.setDate(2, new java.sql.Date(new java.util.Date().getTime()));int i = st.executeUpdate();if (i > 0) {System.out.println("插入成功");}} catch (Exception e) {e.printStackTrace();} finally {try {JdbcUtils.release(conn, st, rs);} catch (SQLException e) {e.printStackTrace();}}} }

    此種方式可以避免sql注入。

    7 JDBC操縱事務

    事務的四大特性:

    • 原子性(Atomictiy):不可再分割
    • 一致性(Consistency):數據前后一致,總量保持不變
    • 隔離性(Isolation):多個事務互不干擾
    • 持久性(Durability):一旦提交不可逆,持久化到數據庫

    事務的隔離級別:

  • 讀未提交(Read Uncommitted):最低級別,存在臟讀、幻讀、不可重復讀問題;
  • 讀已提交(Read Committed):可避免臟讀情況發生;
  • 可重復讀(Repeatable Read):可避免臟讀、不可重復讀情況的發生;
  • 序列化(Serializable):可避免臟讀、不可重復讀、幻讀情況的發生。(串行化)
  • 隔離性問題:

    • 臟讀:一個事務讀取了另一個沒有提交的事務數據
    • 不可重復讀:在同一個事務內,相同的語句讀取出來的數據不一致
    • 幻讀:在一個事務內,讀取到別的數據插入的數據,導致前后讀出來的數據結果條數不一致。
    package com.wzh.demo02;import com.wzh.demo02.utils.JdbcUtils;import java.sql.*;public class JdbcTransaction {public static void main(String[] args) {Connection conn = null;PreparedStatement st = null;ResultSet rs = null;try {conn = JdbcUtils.getConnection();// 關閉自動提交 并且會自動開啟事務conn.setAutoCommit(false);String sql1 = "update user set money = money - 100 where id = 1";st = conn.prepareStatement(sql1);st.executeUpdate();String sql2 = "update user set money = money + 100 where id = 2";st = conn.prepareStatement(sql2);st.executeUpdate();// 業務完畢 提交事務conn.commit();} catch (Exception e) {try {conn.rollback();} catch (SQLException e1) {e1.printStackTrace();}e.printStackTrace();} finally {try {JdbcUtils.release(conn, st, rs);} catch (SQLException e) {e.printStackTrace();}}} }

    修改事務隔離級別

    conn = JdbcUtils.getConnection(); conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);//避免臟讀 conn.setAutoCommit(false);

    8 批處理

    package com.wzh.demo02;import com.wzh.demo02.utils.JdbcUtils;import java.sql.*;public class JdbcDemo04 {public static void main(String[] args) {Connection conn = null;Statement st = null;ResultSet rs = null;try {conn = JdbcUtils.getConnection();conn.setAutoCommit(false); //設為手動提交long start = System.currentTimeMillis();st = conn.createStatement();for (int i = 0; i < 100; i++) {st.addBatch("insert into user (name,birthday) values ('hao'" + i + ",'2021-06-28')");}st.executeBatch();conn.commit(); //提交事務long end = System.currentTimeMillis();System.out.println("插入100條數據,耗時(ms):" + (end - start));} catch (Exception e) {e.printStackTrace();} finally {try {JdbcUtils.release(conn, st, rs);} catch (SQLException e) {e.printStackTrace();}}} }

    以上基本就是jdbc基本的使用方式,后續會再專門寫一篇關于數據庫連接池技術c3p0,dbcp與druid的使用。

    總結

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

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