JDBC基本使用

1. 簡介 JDBC(Java Data Base Connectivity) 是 Java 訪問數據庫的標準規范.,為 多種關系數據庫提供統一訪問。它由一組用Java語言編寫的類和接口組成。 JDBC只是Java提供的一些接口,而這些接口

1. 簡介

JDBC(Java Data Base Connectivity) 是 Java 訪問數據庫的標準規范.,為 多種關系數據庫提供統一訪問。它由一組用Java語言編寫的類和接口組成。

JDBC只是Java提供的一些接口,而這些接口的實現類是由各個數據庫廠商提供的,稱之為數據庫連接驅動。這樣一來,我們就可以面向接口編程,以一種統一的方式訪問多種數據庫。

2. JDBC使用流程

  1. 下載對應版本的數據庫連接驅動,并導入項目。
  2. 注冊驅動
    通過 Class.froName("Driver實現類路徑"); 加載Driver驅動并注冊到DriverManager中。
    對于MySQL而言,不同版本的 "Driver實現類路徑" 也是不同的:
    5.x版本為:com.mysql.jdbc.Driver
    8.x版本為:com.mysql.cj.jdbc.Driver
    原理為: Driver類在靜態代碼塊中創建Driver對象,并注冊到DriverManager中。

**注意:**在JDK1.6中DriverManager明確指出,在JDBC4.0及之后版本中可以不用forName顯示加載驅動。這是因為在獲取連接時,可以根據url判斷并自動加載對應的驅動。但是一般開發中還是 要寫forName,因為有些場合并不會自動加載,如Tomcat中,由于類加載器不同,省略forName就會找不到類。

  1. 創建連接
    通過 DriverManager的getConnection方法獲取連接
Connection getConnection(url,userName,password);
  • url:jdbc:mysql://localhost:3306/test?characterEncoding=UTF-8&serverTimezone=UTC
    jdbc:mysql是 協議 名,固定寫法
    localhost:3306為服務器地址 及 端口號
    test是要連接的數據庫名
    characterEncoding=UTF-8的作用為,告訴mysql,將數據轉化為 utf-8 格式之后再傳給我的程序。
    serverTimezone=UTC有時候不指定時區會報錯。
  • userName 登錄MySQL的用戶名
  • password 密碼
  1. 執行SQL語句
    通過connection對象的createStatement()方法獲取Statement對象,然后通過Statement對象的executeUpdate()executeQuery()方法執行SQL語句:
    executeUpdate():方法用于執行insert update delete語句,返回受影響的行數。
    executeQuery():執行select語句, 返回ResultSet結果集對象。
  2. 處理結果集
    ResultSet的作用為 封裝查詢結果,然后通過其next方法和getXxx方法遍歷結果集。

方法

說明

boolean next()

1) 游標向下一行

2) 返回 boolean 類型,如果還有下一條記錄,返回 true,否則返回 false

xxx getXxx( String or int)

1) 通過列名,參數是 String 類型。返回不同的類型

2) 通過列號,參數是整數,從 1 開始。返回不同的類型

  1. 釋放資源
    釋放原則為:先開的后關,一次關閉 ResultSet對象,Statement對象,Connection對象
  2. 示例
@Test
    public void test(){
        String url = "jdbc:mysql://192.168.65.131:3306/test?characterEncoding=UTF-8&serverTimezone=UTC";
        String userName = "mochen";
        String password = "123456";
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;  // 查詢數據

        try {
            // 加載Driver類,并注冊到DriverManager
            Class.forName("com.mysql.cj.jdbc.Driver");
            // 獲取連接
            conn = DriverManager.getConnection(url, userName, password);
            // 獲取Statement對象
            stmt = conn.createStatement();
            // 執行SQL語句
            stmt.executeUpdate("insert into jdbc_user values(null,'王蛋','abcd','2014-05-12 13:21:00')");  // 插入數據
            rs = stmt.executeQuery("select * from jdbc_user");
            // 處理結果集
            while(rs.next()){
                System.out.println(rs.getString(1)+"\t\t"+rs.getString(2)
                                   +"\t\t"+rs.getString(3)+"\t\t"
                                   +rs.getString(4));
            }
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        } finally { // 釋放資源
            if(null!=rs){
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(null!=stmt){
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(null!=conn){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }

3. SQL注入 與 PreparedStatement

3.1 SQL注入

什么是SQL注入:

當要執行的SQL語句 是由用戶輸入的參數 拼接而來時,如果用戶可以輸入一些有特殊意義的內容,就可以改變原有的SQL的意義,從而進行非法操作。這種情況就稱為SQL注入。

舉例:

如 驗證用戶登錄的SQL語句:

String sql = "select * from jdbc_user " +
"where username = " + " '" + name +"' " +" and password = " +" '" + pass +"'";

如果用戶輸入的密碼為:' or '1'=1因為1=1肯定是真,or 又是有真即真,所以where條件的結果總為true。這就改變了SQL原有的含義。

真正的SQL注入可能要復雜的多,但原理應該都是

3.2 PreparedStatement

1. 簡介

PreparedStatement 是 Statement 接口的子接口,繼承于父接口中所有的方法。它是一個預編譯的 SQL 語 句對象。預編譯:是指SQL 語句被預編譯,并存儲在 PreparedStatement 對象中。然后可以使用此對象多次高效地執行該語句。

2. 使用

// 獲取 PreparedStatement
conn.prepareStatement(String sql);  // Sql中可以使用 ? 作為參數的占位符,然后使用setXxx方法賦值

// 常用方法
int executeUpdate();
ResultSet executeQuery(); // 注意:這里不必填入SQL

JDBC基本使用_bc

3. 示例

PreparedStatement ps = conn.prepareStatement("select * from employee where id=? and name=?");
ps.setInt(1,1);
ps.setString(2,"孫悟空");
rs = ps.executeQuery();
while (rs.next()){
    for(int i=0;i<6;i++){
        System.out.print(rs.getObject(i+1)+"\t");
    }
}

4. JDBC工具類

如何編寫:

  1. 用常量記錄 DRIVERNAME、URL 、USER 、PASSWORD ,也可以用配置文件
  2. 靜態代碼塊中注冊驅動(或者是創建數據源)
  3. 提供靜態方法 獲取連接、 關閉對象。
    其他的方法(像直接執行SQL的方法)就不要提供了,因為如果這樣調用者中就沒有Connection和Statement的引用,而這兩者又只能在處理結果后才能關閉,這就不是靜態方法能夠實現的功能了。
  4. 工具類類一般都是提供靜態方法,不能創建對象。
    我認為所謂工具就是要足夠簡單,獨立,與主程序邏輯沒什么關系。拿來即用,用完就不需要有什么后續操作。所以要用靜態方法。為了保證它的絕對簡單,最好提供private 構造方法,明確禁止創建對象。

示例:

/**
 * JDBC 工具類
 */
public class JDBCUtils {
    //1. 定義字符串常量, 記錄獲取連接所需要的信息
    public static final String DRIVERNAME = "com.mysql.jdbc.Driver";
    public static final String URL = "jdbc:mysql://localhost:3306/db4?characterEncoding=UTF-8";
    public static final String USER = "root";
    public static final String PASSWORD = "123456";
    //2. 靜態代碼塊, 隨著類的加載而加載
    static{
        try {
            //注冊驅動
            Class.forName(DRIVERNAME);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    //3.獲取連接的靜態方法
    public static Connection getConnection(){
        try {
            //獲取連接對象
            Connection connection = DriverManager.getConnection(URL, USER, PASSWORD);
            //返回連接對象
            return connection;
        } catch (SQLException e) {
            e.printStackTrace();
            return null;
        }
    }
    //關閉資源的方法
    public static void close(Connection con, Statement st){
        if(con != null && st != null){
            try {
                st.close();
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    public static void close(Connection con, Statement st, ResultSet rs){
        if(rs != null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        close(con,st);
    }
}

5. 事務控制

mysql的自動事務為每一條DML語句都開啟一個事務。JDBC可以通過關閉自動提交來打開事務。

相關方法:

void setAutoCommit(boolean autoCommit);  // 設置為 false 關閉事務的自動提交
void commit();		// 事務提交
void rollback();    // 事務回滾

示例:

//1. 獲取連接
con = JDBCUtils.getConnection();
//2. 開啟事務
con.setAutoCommit(false);
//3. 獲取到 PreparedStatement 執行兩次更新操作
//3.1 tom 賬戶 -500
ps = con.prepareStatement("update account set money = money - ? where name = ? ");
ps.setDouble(1,500.0);
ps.setString(2,"tom");
ps.executeUpdate();
//模擬tom轉賬后 出現異常
System.out.println(1 / 0);
//3.2 jack 賬戶 +500
ps = con.prepareStatement("update account set money = money + ? where name = ? ");
ps.setDouble(1,500.0);
ps.setString(2,"jack");
ps.executeUpdate();
//4. 正常情況下提交事務
con.commit();
System.out.println("轉賬成功!");

6. 批處理

6.1 簡介

批處理指的是一次操作中執行多條SQL語句,批處理相比于一次一次執行效率會提高很多。主要用途就是批量操作,如一鍵生成一千個用戶,從提交的文件中提取并導入大批量的數據 等。

6.2 實現

Statement和PreparedStatement都支持批處理操作。

相關方法:

void addBatch();  // 將給定的 SQL 命令添加到此 Statement 對象的當前命令列表中。
int[] executeBatch();  // 提交一批命令到數據庫中執行,返回的數組是每條命令所影響的行數

示例:

@Test  // Statement 批處理 測試
public void test135() throws Exception{
    Connection conn = DruidUtils.getConnection();
    Statement stmt = conn.createStatement();
    for(int i=0;i<10;i++) {
        stmt.addBatch("insert into appdate values(123,'豬悟能')");
    }
    int[] ints = stmt.executeBatch();
    System.out.println(Arrays.toString(ints));
}

@Test  // PreparedStatement 批處理 測試
public void test150() throws Exception{
    Connection conn = DruidUtils.getConnection();
    PreparedStatement ps = conn.prepareStatement("insert into appdate values(?,?)");
    for(int i=0;i<10;i++) {
        ps.setInt(1, 123);
        ps.setString(2,"豬悟能");
        ps.addBatch();
    }
    int[] ints = ps.executeBatch();
    System.out.println(Arrays.toString(ints));
}

**注意:**批處理中不能進行查詢

JDBC基本使用_System_02

7. 獲取元數據

相關類:DatabaseMetaData、ResultSetMetaData

使用方法:

DatabaseMetaData:

@Test // DatabaseMetaData 測試
public void test165() throws Exception{
    Connection conn = DruidUtils.getConnection();
    // 通過 Connection 獲取 DatabaseMetaData 對象
    DatabaseMetaData dmd = conn.getMetaData();

    // 通過 DatabaseMetaData 對象(dmd) 獲取 元數據
    System.out.println(dmd.getDriverName());   // 驅動器名,如:MySQL Connector/J
    System.out.println(dmd.getURL());          // 就是連接是傳入的URL 
    System.out.println(dmd.getUserName());     // 登錄的用戶名,如:root@localhost
    System.out.println(dmd.isReadOnly());      // 是否 只讀 

    System.out.println(dmd.getDatabaseProductName());     // 獲取數據庫軟件的名字,如:MySQL
    System.out.println(dmd.getDatabaseProductVersion());  // 獲取數據庫軟件的版本,如:8.0.21
}

ResultSetMetaData

@Test // ResultSetMetaData 測試
public void test178() throws Exception{
    Connection conn = DruidUtils.getConnection();
    PreparedStatement ps = conn.prepareStatement("select * from employee");
    ps.executeQuery();
    // 同過 PreparedStatement 獲取 ResultSetMetaData 對象,注意 Statemet 不行。
    ResultSetMetaData rsmd = ps.getMetaData();
    // 通過 ResultsetMetaData 對象獲取元數據
    System.out.println(rsmd.getColumnCount());  // 獲取結果集的 列數
    System.out.println(rsmd.getColumnName(2)); // 獲取結果集 某一列的列名
    System.out.println(rsmd.getColumnTypeName(2)); // 返回對應列的 數據類型(MySQL類型)名字,如:VARCHAR
    System.out.println(rsmd.getColumnClassName(2)); // 返回對應列的 數據類型對應的java類路徑,如:java.lang.String
}

8. 注意

  1. statement的方法使用說明
execute()
executeUpdate() 可以進行:
    數據的 增 刪 改、
    表的 增 刪 改

executeQuery() 可以查詢:
    表中 數據
    有哪些表 和 數據庫 show tables, show databases
    當前表名 select database()
    表結構 desc 表名 返回 表結構包括:Field、TYPE、NULL、Key、Default、Extra

暫時只能想到這些操作,其余的用到了在補充吧!

  1. Statement與PreparedStatement的選擇
    當一次同一SQL要執行很多次時,選擇preparedStatement。
    當涉及到查詢參數時,使用PreparedStatement。
    其余情況:
    即 只是 簡單的 執行單獨一條SQL語句,也不用有什么參數限制時,使用Statement即可。
    姑且這么認為吧,對不對的 總得先有個判別依據,要不然太混亂了。
聲明:所有內容來自互聯網搜索結果,不保證100%準確性,僅供參考。如若本站內容侵犯了原著者的合法權益,可聯系我們進行處理。
發表評論
更多 網友評論0 條評論)
暫無評論

返回頂部

主站蜘蛛池模板: 3d动漫精品一区视频在线观看| 亚洲a级在线观看| caoporm超免费公开视频| 精品国产污污免费网站| 斗罗大陆动漫完整免费| 国产一级特黄生活片| 久久久久久亚洲精品| 野花视频在线观看免费观看最新| 日韩美aaa特级毛片| 国产强被迫伦姧在线观看无码| 久久这里只精品国产免费10| 黄色a级片免费看| 日本试看60秒做受小视频| 国产免费一区二区三区VR| 久久91精品综合国产首页| 美女网站在线观看视频18| 小蝌蚪app在线观看| 先锋影音av资源网| 91麻豆精品在线观看| 欧美成a人片在线观看久| 国产欧美日韩另类精彩视频| 久久精品影院永久网址| 青草青草视频2免费观看| 成人黄页网站免费观看大全| 再深点灬舒服灬太大了短文d | 精品人妻人人做人人爽夜夜爽| 妇女被猛烈进入在线播放| 亚洲精品无码人妻无码| **性色生活片久久毛片| 最新国产精品拍自在线播放| 国产免费久久精品99re丫y| 中文字幕5566| 特级毛片全部免费播放| 国产精品综合一区二区三区| 乱yin合集3| 美日韩一区二区三区| 天堂俺去俺来也www久久婷婷| 亚洲日韩中文字幕在线播放| 黑人一级大毛片| 成人免费视频国产| 亚洲精品视频在线观看你懂的|