Java JDBC 操作

来源:http://www.cnblogs.com/yueguangmoliya/archive/2017/05/28/6916354.html
-Advertisement-
Play Games

1.簡介 JDBC(Java DataBase Connectivity) 是一種可用於執行SQL語句的Java API,是一套面向對象的應用程式介面, 統一了資料庫的訪問方式,資料庫廠商提供了實現介面的類,稱為‘驅動程式’。因此JDBC並不能直接訪問資料庫, 需要依賴資料庫廠商提供的JDBC驅動程 ...


1.簡介

JDBC(Java DataBase Connectivity) 是一種可用於執行SQL語句的Java API,是一套面向對象的應用程式介面,

統一了資料庫的訪問方式,資料庫廠商提供了實現介面的類,稱為‘驅動程式’。因此JDBC並不能直接訪問資料庫,

需要依賴資料庫廠商提供的JDBC驅動程式。

--SQL語言:

數據定義語言(Data Definition Language,DDL)如:create,alter,drop等

數據操縱語言(Data Manipulation Language,DML)如update,delete等

數據查詢語言(Data Query language,DQL),查詢

數據控制語言(Data Control Language,DCL),如grant,revoke等

事務控制語言(Transaction Control Language,TCL),如commit,rollback等

2.準備工作,以Mysql為例

a.安裝了Mysql 資料庫

b.下載mysql驅動包併在項目中導入jar包:mysql-connector-java-5.1.42-bin.jar 

3.JDBC的操作

步驟:

1.註冊驅動

2.連接資料庫

3.創建語句對象,用於執行SQL

4.執行SQL

5.處理執行結果

6.關閉連接

一、JDBC基本操作

1)在資料庫先建立一張表Student

CREATE TABLE student(
    id INT AUTO_INCREMENT,
    NAME VARCHAR(20),
    age INT ,
    PRIMARY KEY(id)
);

2)jdbc實現

package com.huan.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class JDBCDemo01 {
    public static void main(String[] args) {
        //聲明連接
        Connection connection = null;
        try {
            //載入驅動
            Class.forName("com.mysql.jdbc.Driver");
            //資料庫連接信息
            //地址  jdbc:mysql://地址/資料庫
            String url = "jdbc:mysql://localhost:3306/huan";
            String user = "root";
            String password = "root";
            //獲得連接
            connection = DriverManager.getConnection(url, user, password);
            //語句對象
            Statement st = connection.createStatement();
            String sql = "insert into student (name,age) values ('zhangsan',30)";
            //執行sql  DDL-execute()方法  DML-executeUpdate()方法 DQL-executeQuery()方法
            int n = st.executeUpdate(sql);
            String querySql = "select id,name,age from student";
            ResultSet rs = st.executeQuery(querySql);
            //處理結果
            while(rs.next()){
                int id = rs.getInt("id");
                String name = rs.getString("name");
                int age = rs.getInt("age");
                System.out.println("id:"+id+" name:"+name+" age:"+age);
            }
            //釋放資源
            rs.close();
            st.close();
            
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally {
            //關閉連接
            if(connection != null){
                try {
                    connection.close();
                } catch (SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
        
    }
}

上面先執行了一條插入語句,由於主鍵id是自增的,因此直插入了名字zhangsan和年齡30,然後查詢了表的數據

輸出如下:

id:1 name:zhangsan age:30

二、JDBC連接的封裝

由於連接資料庫的過程都是一樣,為了提高代碼的重用,可以將資料庫的連接封裝起來:

首先將資料庫的連接信息放到配置文件中,比如在項目根目錄下新建文件db.properties,如下:

#db.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/huan
jdbc.user=root
jdbc.password=root

JDBCUtil類

package com.huan.jdbc;

import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;


public class JDBCUtil {
    
    private static String driverClass;
    private static String url;
    private static String user;
    private static String password;
    //靜態塊載入資料庫配置屬性
    static{
        Properties config = new Properties();
        try {
            config.load(new FileInputStream("db.properties"));
        } catch (Exception e) {
            e.printStackTrace();
        }
        driverClass = config.getProperty("jdbc.driver");
        url = config.getProperty("jdbc.url");
        user = config.getProperty("jdbc.user");
        password =config.getProperty("jdbc.password");
    }
    
    
    //獲取資料庫連接
    public static Connection getConnection() throws SQLException {
        
        try {
            Class.forName(driverClass);
            Connection connection = DriverManager.getConnection(url, user, password);
            return connection;
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            throw new SQLException("沒有找到驅動",e);
        }

    }
    
    //關閉資源
    public static void close(Connection connection,Statement st,ResultSet rs){
        
        if(connection != null){
            try {
                connection.close();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        
        if(st != null){
            try {
                st.close();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        
        if(rs != null){
            try {
                rs.close();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        
    }
    
}

測試JDBCUtil

package com.huan.jdbc;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class JDBCUtilTest {
    public static void main(String[] args) {
        Connection connection = null;
        Statement st = null;
        ResultSet rs =null;
        try {
            connection = JDBCUtil.getConnection();
            String sql = "select id ,name ,age from student" ;
            st = connection.createStatement();
            rs = st.executeQuery(sql);
            while(rs.next()){
                int id = rs.getInt("id");
                String name = rs.getString("name");
                int age = rs.getInt("age");
                System.out.println("id:"+id+" name:"+name+" age:"+age);
            }
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally {
            JDBCUtil.close(connection, st, rs);
        }
        
        
        
    }
}

輸出:

id:1 name:zhangsan age:30

三 SQL預處理及事務

SQL預處理:在之前的處理中都是將sql語句發送到資料庫,有資料庫的sql解釋器把sql語句生成底層的內部命令,然後執行命令,完成操作,當前不斷的

                  向資料庫發送sql語句,會增加資料庫sq解釋器的負擔,影響執行速度。

                  而Connection的prepareStatement(Stirng sql)方法能夠對sql語句進行預處理,生成數據底層的命令,並封裝在PrepareStatement對

                  象中,通過對應的方法執行底層資料庫的命令,從而減輕資料庫的負擔,提高訪問速度。

                  並且之前的sql都是拼接的,當帶參數拼接時容易造成SQL的註入(參數中含有sql成分,改變原有的sql語句邏輯),而PrepareStatement在

                 編譯之後,其中的sql執行計劃已經確定,當替換參數時不會改變執行計劃,因此可以避免sql註入。

事務控制:   當我們在編寫邏輯的時候,存在多條的插入或者更新語句,前面的sql成功執行之後出現錯誤,這時導致業務邏輯中斷,而執行成功的數據已經

                 存入資料庫,從而導致數據不完整。為避免這種事情的發生就需要手動進行事務控制。

                1.關閉自動提交--connection.setAutoCommit(false);

                2.業務執行完成後提交-connection.commit();

                3.在遇到異常時回滾-connection.rollback();

package com.huan.jdbc;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;

public class PrepareStatementDemo {
    public static void main(String[] args) {
        Connection connection = null;
        //SQL預處理對象
        PreparedStatement ps = null;
        ResultSet rs =null;
        
        try {
            connection = JDBCUtil.getConnection();
            connection.setAutoCommit(false);
            //?代表參數
            String sql = "insert into student (name,age) values(?,?)";
            //編譯預執行計劃 在資料庫上創建執行計劃  
            //(第二個參數可以不要-Statement.RETURN_GENERATED_KEYS 代表返回主鍵,沒有的話下麵的要去掉ps.getGeneratedKeys()會)
            ps = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
            //?的位置 和 替換的值
            ps.setString(1, "lisi");
            ps.setInt(2, 20);
            //n 更新結果的數量
            int n = ps.executeUpdate();
            System.out.println("成功插入"+n+"條數據");
            //獲取插入成功數據的主鍵
            ResultSet keySet = ps.getGeneratedKeys();
            int key = -1;
            while(keySet.next()){
                key = keySet.getInt(1);
            }
            System.out.println("插入數據的主鍵:"+key);
            //查詢
            String querySql = "select id , name ,age from student";
            ps = connection.prepareStatement(querySql);
            rs = ps.executeQuery();
            //獲取結果集的元數據相關信息
            ResultSetMetaData metaData = rs.getMetaData();
            //列數
            int count = metaData.getColumnCount();
            for(int i = 1; i <= count; i++){
                System.out.print(metaData.getColumnName(i)+" ");
            }
            System.out.println();
            //查詢結果列印
            while(rs.next()){
                int id = rs.getInt("id");
                String name = rs.getString("name");
                int age = rs.getInt("age");
                System.out.println(id+" "+name+" "+age);
            }
            //提交
            connection.commit();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            if(connection != null){
                try {
                    //出現異常回滾
                    connection.rollback();
                } catch (SQLException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
            }
        }finally {
            JDBCUtil.close(connection, ps, rs);
        }

    }
}

輸出結果:

成功插入1條數據
插入數據的主鍵:2
id name age 
1 zhangsan 30
2 lisi 20

成功插入了 lisi 這條記錄,且返回主鍵為2.最後列印了列名和查詢得到的數據

這裡用了事務的回滾,如果保存完之後再查詢的中間出現異常,數據是不會存到資料庫的,可以動手試下。

四、JDBC的批量操作

PrepareStatement和Statement都提供了可以批量操作SQL的方法

1.將sql添加至緩存區

Statement: addBatch(sql)方法,可以將sql直接添加Statement緩存區;

PrepareStatement:需要先執行setxxx(n,參數)方法將參數賦值,然後調用addBatch(sql)方法

2.執行executeBatch()將參數批量發送到資料庫,並且執行

3.可以使用clearBatch()清空緩存區的參數或者sql

package com.huan.jdbc;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Arrays;

import org.junit.Test;

public class JDBCBatchDemo {

    
    @Test
    public void testJdbcPrepareBatch(){
        
        Connection connection = null;
        PreparedStatement ps = null;
        
        try {
            connection = JDBCUtil.getConnection();
            String sql  = "insert into student (name,age) values (?,?)";
            ps = connection.prepareStatement(sql);
            ps.setString(1, "ps1");
            ps.setInt(2, 11);
            ps.addBatch();
            ps.setString(1, "ps2");
            ps.setInt(2, 12);
            ps.addBatch();
            int [] n = ps.executeBatch();
            System.out.println(Arrays.toString(n));    
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        
        
        
    }
    
    
    @Test
    public void testJdbcStatementBatch(){
        Connection connection = null;
        Statement st = null;
        try {
            connection = JDBCUtil.getConnection();
            String sql1 = "insert into student(name,age) values('statement1',20)";
            String sql2 = "insert into student(name,age) values('statement2',30)";
            String sql3 = "insert into student(name,age) values('statement3',40)";
            
            st = connection.createStatement();
            //批量添加
            st.addBatch(sql1);
            st.addBatch(sql2);
            st.addBatch(sql3);
            //執行
            int [] n = st.executeBatch();
                    
            System.out.println(Arrays.toString(n));
            
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally{
            JDBCUtil.close(connection, st, null);
        }
    }
    
    
}

testJdbcStatementBatch()測試方法完成後查看資料庫,數據成功添加:

image

testJdbcPrepareBatch()測試方法執行之後查看資料庫,數據成功添加:

image

五、連接池(數據源)的使用

連接池能夠重用資料庫的連接,控制資料庫的連接總數,當關閉從連接池中獲取的連接時,只是將此連接歸還給連接池,沒有真正的與資料庫斷開連接。

重用的連接池有:DBCP和c3p0

1)c3p0的使用

官網下載jar包,將c3p0-0.9.5.2.jar和mchange-commons-java-0.2.11.jar加入項目中。

package com.huan.jdbc;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import com.mchange.v2.c3p0.ComboPooledDataSource;


public class C3p0DataSourceDemo {
    
    public static void main(String[] args) {
        Connection connection = null;
        
        try {
            ComboPooledDataSource cpds = new ComboPooledDataSource();
            //配置連接池參數
            cpds.setDriverClass("com.mysql.jdbc.Driver");
            cpds.setJdbcUrl("jdbc:mysql://localhost:3306/huan");
            cpds.setUser("root");
            cpds.setPassword("root");
            //連接池的管理策略 ...
            //最小連接數量
            cpds.setMinPoolSize(5);
            //最大連接數量
            cpds.setMaxPoolSize(20);
            //超時時間ms
            cpds.setCheckoutTimeout(10000);
            //獲取連接
            connection = cpds.getConnection();
            String sql = "select id,name,age from student";
            PreparedStatement ps = connection.prepareStatement(sql);
            ResultSet rs = ps.executeQuery();
            while(rs.next()){
                int id = rs.getInt("id");
                String name = rs.getString("name");
                int age = rs.getInt("age");
                System.out.println("id:"+id+" name:"+name+" age:"+age);
            }
            
            rs.close();
            ps.close();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally {
            try {
                connection.close();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

    }
    
}

輸出結果:

id:1 name:zhangsan age:30
id:2 name:lisi age:20
id:3 name:statement1 age:20
id:4 name:statement2 age:30
id:5 name:statement3 age:40
id:6 name:ps1 age:11
id:7 name:ps2 age:12

2)DBCP的使用

官網下載jar包,將commons-logging-1.2.jar,commons-dbcp2-2.1.1.jar和commons-pool2-2.4.2.jar下載後導入項目

package com.huan.jdbc;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.apache.commons.dbcp2.BasicDataSource;

public class DBCPDemo {
    public static void main(String[] args) {
        Connection connection = null;

        try {
            BasicDataSource bds = new BasicDataSource();
            // 連接參數
            bds.setDriverClassName("com.mysql.jdbc.Driver");
            bds.setUrl("jdbc:mysql://localhost:3306/huan");
            bds.setUsername("root");
            bds.setPassword("root");
            // 管理策略參數
            bds.setInitialSize(5);
            bds.setMinIdle(5);
            bds.setMaxTotal(20);
            bds.setMaxWaitMillis(10000);

            connection = bds.getConnection();
            String sql = "select id,name,age from student";
            PreparedStatement ps = connection.prepareStatement(sql);
            ResultSet rs = ps.executeQuery();
            while (rs.next()) {
                int id = rs.getInt("id");
                String name = rs.getString("name");
                int age = rs.getInt("age");
                System.out.println("id:" + id + " name:" + name + " age:" + age);
            }

            rs.close();
            ps.close();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            try {
                if (connection != null) {
                    connection.close();
                }

            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

    }

}

輸出結果:

id:1 name:zhangsan age:30
id:2 name:lisi age:20
id:3 name:statement1 age:20
id:4 name:statement2 age:30
id:5 name:statement3 age:40
id:6 name:ps1 age:11
id:7 name:ps2 age:12

關於JDBC的一些總結就寫這麼多了~~


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • random 我們經常看到網站的隨機驗證碼,這些都是由隨機數生成的,因此我們需要瞭解一下隨機數的模塊。如何生成隨機數。 random 生成隨機數 random.random() 生成0-1之間的小數 >>> import random >>> random.random() 0.7386445925 ...
  • time模塊 time模塊提供各種操作時間的函數 #1、時間戳 1970年1月1日之後的秒 #2、元組 包含了:年、日、星期等... time.struct_time #3、格式化的字元串 2014-11-11 11:11 (1)asctime(p_tuple=None) def asctime(p ...
  • eclipse啟動時彈出Failed to create the Java Virtual Machine 一、現象 今天裝eclipse的時候出現Failed to create the Java Virtual Machine 的錯誤。 錯誤圖片如下: 二、出錯原因 把錯誤提示翻譯一下,就是“無 ...
  • Ctrl+1 快捷修複 Ctrl+D 快捷刪除 shift+enter 跳過本行開始下一行 Ctrl+F11 快速運行 Alt+↑/↓ 快速移動行 Ctrl+Alt+↑/↓ 快速複製行 Ctrl+M 視窗最大化 Alt+/ 自動補全 代碼區域右鍵 選中preferences →Java →edito ...
  • 國際化英文單詞為:Internationalization,又稱I18N,I為因為單詞的第一個字母,18為這個單詞的長度,而N代表這個單詞的最後一個字母。國際化又稱本地化(Localization,L10N)。 Java國際化主要通過如下3個類完成 java.util.ResourceBundle:... ...
  • Socket簡介: Socket稱為“套接字”,描述IP地址和埠。在Internet上的主機一般運行多個服務軟體,同時提供幾種服務,每種服務都打開一個Socket,並綁定在一個埠上,不同的埠對應於不同的服務。Socket和ServerSocket類位於java.net包中。ServerSock ...
  • 1、在(x1,y1) (x2,y2)兩點構成的線段(不含端點)上有gcd(x1-x2,y1-y2)-1個整點。 2、兩個longlong相乘後%一個數可以以下述方法避免高精度 3、$\sum\limits_{i=1}^n i^2=\frac{n(n+1)(n+2)}{6}$ 4、函數前面加inlin ...
  • 在日常的開發中我們經常會碰到對文件的操作,在java中對文件的操作都在java.io包下,這個包下的類有File、inputStream、outputStream、FileInputStream、FileOutputStream、reader、writer、FileReader、FileWriter ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...