JDBC技术详解
文章目錄
- 1 綜述
- 2 JDBC相關(guān)概念
- 2.1 什么是JDBC
- 2.2 JDBC有什么用
- 2.3 數(shù)據(jù)庫驅(qū)動
- 2.4 JDBC架構(gòu)
- 2.4.1 雙層結(jié)構(gòu)
- 2.4.2 三層架構(gòu)
- 3 JDBC常用接口
- 3.1 Driver接口
- 3.2 Connection接口
- 3.3 Statement接口
- 3.4 ResultSet接口
- 4 JDBC使用方法
- 4.1 下載jar包
- 4.2 導(dǎo)入jar包
- 4.3 JDBC使用步驟
- 4.4 使用代碼示例
- 4.4.1 插入更新操作
- 5 封裝提取工具類
- 6 SQL注入
- 6.1 sql注入演示
- 6.2 PreparedStatement使用示例
- 7 JDBC操縱事務(wù)
- 8 批處理
1 綜述
本文檔主要對JDBC進(jìn)行詳細(xì)說明,包括JDBC的相關(guān)概念、架構(gòu)說明、工作原理、常用接口以及具體的使用方法等。
2 JDBC相關(guān)概念
2.1 什么是JDBC
JDBC英文名為:Java Data Base Connectivity(Java數(shù)據(jù)庫連接)
官方解釋它是Java編程語言和廣泛的數(shù)據(jù)庫之間獨(dú)立于數(shù)據(jù)庫的連接標(biāo)準(zhǔn)的Java API,根本上說JDBC是一種規(guī)范,它提供的接口,一套完整的,允許便捷式訪問底層數(shù)據(jù)庫。可以用JAVA來寫不同類型的可執(zhí)行文件:JAVA應(yīng)用程序、JAVA Applets、Java Servlet、JSP等,不同的可執(zhí)行文件都能通過JDBC訪問數(shù)據(jù)庫,又兼?zhèn)浯鎯Φ膬?yōu)勢。簡單說它就是JAVA與數(shù)據(jù)庫的連接的橋梁或者插件,用JAVA代碼就能操作數(shù)據(jù)庫的增刪改查、存儲過程、事務(wù)等。
2.2 JDBC有什么用
我們用JAVA就能連接到數(shù)據(jù)庫;創(chuàng)建SQL或者M(jìn)YSQL語句;執(zhí)行SQL或MYSQL的查詢數(shù)據(jù)庫;查看和修改結(jié)果記錄。
2.3 數(shù)據(jù)庫驅(qū)動
我們安裝好數(shù)據(jù)庫之后,我們的應(yīng)用程序也是不能直接使用數(shù)據(jù)庫的,必須要通過相應(yīng)的數(shù)據(jù)庫驅(qū)動程序,通過驅(qū)動程序去和數(shù)據(jù)庫打交道。其實(shí)也就是數(shù)據(jù)庫廠商的JDBC接口實(shí)現(xiàn),即對Connection等接口的實(shí)現(xiàn)類的jar文件。
下載地址:https://mvnrepository.com/artifact/mysql/mysql-connector-java
2.4 JDBC架構(gòu)
分為雙層架構(gòu)和三層架構(gòu)。
2.4.1 雙層結(jié)構(gòu)
- 作用:此架構(gòu)中,Java Applet 或應(yīng)用直接訪問數(shù)據(jù)源。
- 條件:要求 Driver 能與訪問的數(shù)據(jù)庫交互。
- 機(jī)制:用戶命令傳給數(shù)據(jù)庫或其他數(shù)據(jù)源,隨之結(jié)果被返回。
- 部署:數(shù)據(jù)源可以在另一臺機(jī)器上,用戶通過網(wǎng)絡(luò)連接,稱為 C/S配置(可以是內(nèi)聯(lián)網(wǎng)或互聯(lián)網(wǎng))。
2.4.2 三層架構(gòu)
3 JDBC常用接口
3.1 Driver接口
Driver接口由數(shù)據(jù)庫廠家提供,作為java開發(fā)人員,只需要使用Driver接口就可以了。在編程中要連接數(shù)據(jù)庫,必須先裝載特定廠商的數(shù)據(jù)庫驅(qū)動程序,不同的數(shù)據(jù)庫有不同的裝載方法。如:
- 裝載MySql驅(qū)動:
- 裝載Oracle驅(qū)動:
3.2 Connection接口
Connection與特定數(shù)據(jù)庫的連接,在連接上下文中執(zhí)行sql語句并返回結(jié)果。DriverManager.getConnection(url, user, password)方法建立在JDBC URL中定義的數(shù)據(jù)庫Connection連接上。
- 連接MySql數(shù)據(jù)庫:
- 連接Oracle數(shù)據(jù)庫:
- 連接SqlServer數(shù)據(jù)庫:
常用方法:
- createStatement():創(chuàng)建向數(shù)據(jù)庫發(fā)送sql的statement對象。
- prepareStatement(sql) :創(chuàng)建向數(shù)據(jù)庫發(fā)送預(yù)編譯sql的PrepareSatement對象。
- prepareCall(sql):創(chuàng)建執(zhí)行存儲過程的callableStatement對象。
- setAutoCommit(boolean autoCommit):設(shè)置事務(wù)是否自動提交。
- commit() :在鏈接上提交事務(wù)。
- rollback() :在此鏈接上回滾事務(wù)。
3.3 Statement接口
用于執(zhí)行靜態(tài)SQL語句并返回它所生成結(jié)果的對象。
三種Statement類:
常用Statement方法:
- execute(String sql):運(yùn)行語句,返回是否有結(jié)果集
- executeQuery(String sql):運(yùn)行select語句,返回ResultSet結(jié)果集。
- executeUpdate(String sql):運(yùn)行insert/update/delete操作,返回更新的行數(shù)。
- addBatch(String sql) :把多條sql語句放到一個批處理中。
- executeBatch():向數(shù)據(jù)庫發(fā)送一批sql語句執(zhí)行。
3.4 ResultSet接口
ResultSet提供檢索不同類型字段的方法,常用的有:
- getString(int index)、getString(String columnName):獲得在數(shù)據(jù)庫里是varchar、char等類型的數(shù)據(jù)對象。
- getFloat(int index)、getFloat(String columnName):獲得在數(shù)據(jù)庫里是Float類型的數(shù)據(jù)對象。
- getDate(int index)、getDate(String columnName):獲得在數(shù)據(jù)庫里是Date類型的數(shù)據(jù)。
- getBoolean(int index)、getBoolean(String columnName):獲得在數(shù)據(jù)庫里是Boolean類型的數(shù)據(jù)。
- getObject(int index)、getObject(String columnName):獲取在數(shù)據(jù)庫里任意類型的數(shù)據(jù)。
- 等還有其他的獲取類型方法。
ResultSet還提供了對結(jié)果集進(jìn)行滾動的方法:
- next():移動到下一行
- Previous():移動到前一行
- absolute(int row):移動到指定行
- beforeFirst():移動resultSet的最前面。
- afterLast():移動到resultSet的最后面。
注意:使用后依次關(guān)閉對象及連接:ResultSet → Statement → Connection。
4 JDBC使用方法
4.1 下載jar包
上面以及展示下載地址,下載合適的版本即可。
4.2 導(dǎo)入jar包
4.3 JDBC使用步驟
使用JDBC的步驟:
4.4 使用代碼示例
package com.wzh.demo01;import java.sql.*;public class JdbcDemo01 {public static void main(String[] args) throws ClassNotFoundException, SQLException {// 1 加載JDBC驅(qū)動程序Class.forName("com.mysql.jdbc.Driver");// 2 構(gòu)造數(shù)據(jù)庫鏈接信息(以MySql為例)String url = "jdbc:mysql://localhost:3306/test_go?useUnicode=true&characterEncoding=utf8&useSSL=true";String username = "root";String pwd = "root";// 3 建立數(shù)據(jù)庫連接ConnectionConnection connection = DriverManager.getConnection(url, username, pwd);// 4 創(chuàng)建執(zhí)行SQL的語句Statement對象Statement statement = connection.createStatement();// 5 使用Statement對象執(zhí)行SQLString sql = "select * from user";ResultSet resultSet = statement.executeQuery(sql);// 6 處理執(zhí)行結(jié)果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 釋放資源 (注意關(guān)閉順序)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("插入數(shù)據(jù)成功"); }String sql1 = "update user set name='nn' where id = 2"; int i1 = statement.executeUpdate(sql1); if(i1 > 0){System.out.println("更新數(shù)據(jù)成功"); }5 封裝提取工具類
6 SQL注入
詳細(xì)可觀看此篇博文: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();// 區(qū)別:先寫sql// 使用 ? 占位符代替參數(shù)String sql_i = "insert into user(name,birthday) value (?,?)";st = conn.prepareStatement(sql_i); // 預(yù)編譯sql,// 手動給參數(shù)賦值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操縱事務(wù)
事務(wù)的四大特性:
- 原子性(Atomictiy):不可再分割
- 一致性(Consistency):數(shù)據(jù)前后一致,總量保持不變
- 隔離性(Isolation):多個事務(wù)互不干擾
- 持久性(Durability):一旦提交不可逆,持久化到數(shù)據(jù)庫
事務(wù)的隔離級別:
隔離性問題:
- 臟讀:一個事務(wù)讀取了另一個沒有提交的事務(wù)數(shù)據(jù)
- 不可重復(fù)讀:在同一個事務(wù)內(nèi),相同的語句讀取出來的數(shù)據(jù)不一致
- 幻讀:在一個事務(wù)內(nèi),讀取到別的數(shù)據(jù)插入的數(shù)據(jù),導(dǎo)致前后讀出來的數(shù)據(jù)結(jié)果條數(shù)不一致。
修改事務(wù)隔離級別
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); //設(shè)為手動提交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(); //提交事務(wù)long end = System.currentTimeMillis();System.out.println("插入100條數(shù)據(jù),耗時(ms):" + (end - start));} catch (Exception e) {e.printStackTrace();} finally {try {JdbcUtils.release(conn, st, rs);} catch (SQLException e) {e.printStackTrace();}}} }以上基本就是jdbc基本的使用方式,后續(xù)會再專門寫一篇關(guān)于數(shù)據(jù)庫連接池技術(shù)c3p0,dbcp與druid的使用。
總結(jié)
- 上一篇: robotframework 常用关键字
- 下一篇: web 三联发票针式打印_打印机共享操作