JDBC-02

来源:https://www.cnblogs.com/Charles-H/archive/2020/04/06/Learning_JDBC02.html
-Advertisement-
Play Games

JDBC 前言 在JDBC-01當中,我們簡單地學習了有關JDBC的一些基本操作,現在我們再一次進行深入的學習。 正文 事務 首先,我們來學習的是JDBC中事務的運用,那麼讓我們再次瞭解一下事務的概念。 事務的概念 事務指的是邏輯上的一組操作,組成這組操作各個邏輯單元要麼全部成功,要麼全部失敗。 關 ...


JDBC

前言

  在JDBC-01當中,我們簡單地學習了有關JDBC的一些基本操作,現在我們再一次進行深入的學習。

 

正文

事務

  首先,我們來學習的是JDBC中事務的運用,那麼讓我們再次瞭解一下事務的概念。

事務的概念

  事務指的是邏輯上的一組操作,組成這組操作各個邏輯單元要麼全部成功,要麼全部失敗。

關於事務的API

getAutoCommit()

 

commit()

 

rollback()

 

 

異常案例:

package com.charles.jdbc.high;

import org.junit.Test;

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

/**
 * 有關事務的案例
 * 轉賬案例
 * @author Charles
 */
public class Demo01 {
    @Test
    public void demo(){
        Connection conn = null;
        PreparedStatement pste = null;
        try {
            // 載入驅動 + 獲取連接
            conn = org.charl.Demo.getConnection();
            // 編寫SQL
            String sql = "update account set money = money + ? where name = ?";
            // 預編譯
            pste = conn.prepareStatement(sql);
            // 轉賬過程
            pste.setInt(1,-1000);
            pste.setString(2,"aaa");
            pste.executeUpdate();
            pste.setInt(1,1000);
            pste.setString(2,"bbb");
            pste.executeUpdate();
            // 因為這個錯誤,導致異常的發生
            int i = 1 / 0;
        } catch (SQLException e){
            e.printStackTrace();
        } finally {
            // 資源釋放
            org.charl.Demo.release(pste,conn);
        }



    }
}

 

修改後的案例

package com.charles.jdbc.high;

import org.junit.Test;

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

/**
 * 有關事務的案例
 * 轉賬案例
 * @author Charles
 */
public class Demo01 {
    @Test
    public void demo(){
        Connection conn = null;
        PreparedStatement pste = null;
        try {
            // 載入驅動 + 獲取連接
            conn = org.charl.Demo.getConnection();
            // 開啟事務
            conn.setAutoCommit(false);
            // 編寫SQL
            String sql = "update account set money = money + ? where name = ?";
            // 預編譯
            pste = conn.prepareStatement(sql);
            // 轉賬過程
            pste.setInt(1,-1000);
            pste.setString(2,"aaa");
            pste.executeUpdate();
            pste.setInt(1,1000);
            pste.setString(2,"bbb");
            pste.executeUpdate();
            // 因為這個錯誤,導致異常的發生
//            int i = 1 / 0;
            conn.commit();
        } catch (SQLException e){
            // 回滾事務
            try {
                conn.rollback();
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
            e.printStackTrace();
        } finally {
            // 資源釋放
            org.charl.Demo.release(pste,conn);
        }



    }
}

這樣,數據就會進行回滾,保證了數據的安全性。

 

連接池

概念:連接池是創建和管理一個連接的緩衝池的技術,這些連接準備好被任何需要它們的線程使用。

好處(作用):

  • 減少連接創建時間
  • 簡化的編程模式
  • 受控的資源使用
  • 提高連接的效率

 

連接池原理:

 

自定義連接池:

  我們可以利用DataSource介面來實現一個自定義連接池

 

具體步驟:

  1. 編寫一個類實現DataSource介面

  2. 重寫一個getConnection方法

  3. 初始化多個連接在記憶體中

  4. 編寫歸還連接的方法

 

具體實現:

/**
 * 自定義連接池
 * @author Charles
 */
public class MyDataSource implements DataSource {
    // 在初始化的時候提供一些連接
    private List<Connection> connectionList = new ArrayList<Connection>();
    public MyDataSource(){
        // 初始化連接
        for (int i = 1; i <= 4; i++){
            // 向集合中存入連接
            connectionList.add(org.charl.Demo.getConnection());
        }
    }
    // 獲得連接的方法
    @Override
    public Connection getConnection(String username, String password) throws SQLException {
        Connection conn = connectionList.remove(0);
        return conn;
    }

    // 歸還連接的方法
    public void addBack(Connection conn){
        connectionList.add(conn);
    }

 

代碼案例:

package jdbc.datasources;

import org.junit.Test;

import javax.management.relation.Relation;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * 利用連接池的案例
 */
public class Demo01 {
    @Test
    public void demo(){
        Connection conn = null;
        PreparedStatement preparedStatement = null;
        ResultSet rs = null;
        MyDataSource md = null;

        try{
            // 利用自定義的連接池註冊驅動 + 獲得連接
            md = new MyDataSource();
            conn = md.getConnection();
            // 編寫SQL語句
            String sql = "select * from account";
            preparedStatement = conn.prepareStatement(sql);
            rs = preparedStatement.executeQuery();
            // 遍歷結果
            while (rs.next()){
                System.out.println(rs.getInt("id") + " " + rs.getString("name") + " "
                        + rs.getString("money"));
            }

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            // 釋放資源
            if (preparedStatement != null){
                try{
                    preparedStatement.close();
                } catch (SQLException e){
                    e.printStackTrace();
                }
                preparedStatement = null;
            }

            if (rs != null){
                try {
                    rs.close();
                }catch (SQLException e){
                    e.printStackTrace();
                }
                rs = null;
            }

            // 歸還連接
            md.addBack(conn);

        }
    }
}

 

Druid開源連接池

  Druid 是阿裡旗下的開源連接池產品,使用非常簡單,可以與Spring 框架進行快速整合。

 

Maven導包

 

    <!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.1.21</version>
    </dependency>

 

 

 

 

基本代碼實現

 

package com.charles.datasource.demo1;

import com.alibaba.druid.pool.DruidDataSource;
import org.junit.Test;

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

public class DruidDemo1 {

    @Test
    public void demo01(){
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;

        try {
            // 使用連接池
            DruidDataSource druidDataSource = new DruidDataSource();
            druidDataSource.setDriverClassName("com.mysql.jdbc.Driver");
            druidDataSource.setUrl("jdbc:mysql:///web_test3");
            druidDataSource.setUsername("root");
            druidDataSource.setPassword("1234");

// 獲得連接
            connection = druidDataSource.getConnection();
            // 編寫SQL
            String sql = "select * from user";
            // 預編譯sql
            preparedStatement = connection.prepareStatement(sql);
            resultSet = preparedStatement.executeQuery();
            while (resultSet.next()){
                System.out.println(resultSet.getInt("id") + " " + resultSet.getString("username")
                        + " " + resultSet.getString("password"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                preparedStatement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }



    }
}

 

 

 

當然也可以將這些資料庫信息向外面引入,即創建一個db.properties

代碼實現:

單元測試類

    @Test
    public void Demo02(){
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;

        try {
            // 使用連接池
            Properties properties = new Properties();
            properties.load(new FileInputStream("src/main/resources/db.properties"));
            DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);

            // 獲得連接
            connection = dataSource.getConnection();
            // 編寫SQL
            String sql = "select * from user";
            // 預編譯sql
            preparedStatement = connection.prepareStatement(sql);
            resultSet = preparedStatement.executeQuery();
            while (resultSet.next()){
                System.out.println(resultSet.getInt("id") + " " + resultSet.getString("username")
                        + " " + resultSet.getString("password"));
            }
        } catch (SQLException | FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                preparedStatement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

 

 

 

db.properties

# 連接設置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///web_test3
username=root
password=1234

# 初始化連接
initialSize=10

# 最大連接數量
maxActive=50

# 最大空閑連接
maxIdle=20

# 最小空閑連接
minIdle=5

# 超時等待時間(以毫秒為單位)
maxWait=60000

 

 

C3P0連接池

  C3P0是一個開源的JDBC連接池,它實現了數據源和JNDI綁定,支持JDBC3規範和JDBC2的標準擴展。

 

使用方法與Druid相類似

 

Maven導包

 

<!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
<dependency>
    <groupId>com.mchange</groupId>
    <artifactId>c3p0</artifactId>
    <version>0.9.5.2</version>
</dependency>

 

 

 

基本代碼實現

 

package com.charles.datasource.demo1;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.junit.Test;

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

public class C3p0 {

    @Test
    public void demo01() {
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;

        try {
            // 使用連接池
            ComboPooledDataSource DataSource = new ComboPooledDataSource();
            DataSource.setDriverClass("com.mysql.jdbc.Driver");
            DataSource.setJdbcUrl("jdbc:mysql:///web_test3");
            DataSource.setUser("root");
            DataSource.setPassword("1234");

            // 獲得連接
            connection = DataSource.getConnection();
            // 編寫SQL
            String sql = "select * from user";
            // 預編譯sql
            preparedStatement = connection.prepareStatement(sql);
            resultSet = preparedStatement.executeQuery();
            while (resultSet.next()) {
                System.out.println(resultSet.getInt("id") + " " + resultSet.getString("username")
                        + " " + resultSet.getString("password"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (PropertyVetoException e) {
            e.printStackTrace();
        } finally {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                preparedStatement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

 

 

 

當然,C3P0連接池也可以通過外部配置文件引用

具體代碼實現:

 

c3p0-config.xml配置文件

<?xml version="1.0" encoding="utf-8"?>
<c3p0-config>
    <default-config>
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql:///web_test3</property>
        <property name="user">root</property>
        <property name="password">1234</property>

        <property name="initialPoolSize">5</property>
        <property name="maxPoolSize">20</property>
        <property name="minPoolSize">5</property>
    </default-config>

</c3p0-config>

 

 

 

 

單元測試類

    @Test
    public void Demo02(){
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;

        try {
            // 使用連接池
            ComboPooledDataSource DataSource = new ComboPooledDataSource();
            DataSource.setDriverClass("com.mysql.jdbc.Driver");
            DataSource.setJdbcUrl("jdbc:mysql:///web_test3");
            DataSource.setUser("root");
            DataSource.setPassword("1234");

            // 獲得連接
            connection = DataSource.getConnection();
            // 編寫SQL
            String sql = "select * from user";
            // 預編譯sql
            preparedStatement = connection.prepareStatement(sql);
            resultSet = preparedStatement.executeQuery();
            while (resultSet.next()) {
                System.out.println(resultSet.getInt("id") + " " + resultSet.getString("username")
                        + " " + resultSet.getString("password"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (PropertyVetoException e) {
            e.printStackTrace();
        } finally {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                preparedStatement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

 

 

 

這裡註意,只要將配置文件放在預設路徑下,它就會自動查找,不需要手動導入。

 

DBUtils

  Commons DbUtils一個對JDBC進行簡單封裝的工具類庫,它能夠簡化JDBC應用程式的開發,同時也不會影響程式的性能。

 

為什麼要學習DBUTILES?

 

  兩個字:方便   ----->  一個字:懶

 

 

DBUtils常用的API:

QuerryRunner 和 DBUtils,具體查API文檔

 

DBUtils的CRUD操作:(實例源於黑馬,博主在這偷個懶)

添加:

 

修改:

 

刪除:

 

查詢單條(前提創造實體類):

 

查詢多條(前提創造實體類):

 

ResultSetHandler的實現類:

ArrayHandler 和 ArrayListHandler:

 

 

BeanHandler 和 BeanListHandler (重要!!):

 

MapHandler 和 MapListHandler:

 

ColumnListHandler 和 ScalarHandler 還有 KeyedHandler:

ColumnListHandler:

 

ScalarHandler:查詢表中有多少列

 

KeyedHandler:

 

 

 

小結

  以上便是JDBC的內容了,多練,練到煩了就會了。當然為了更偷懶,我們後期將會學到Mybatis,這個框架比JDBC更方便。

                                   加油!

                             時間:2020-04-06 01:41:37


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

-Advertisement-
Play Games
更多相關文章
  • 文檔地址:https://terryz.gitee.io/selectpage/guide.html ...
  • 每天我們打開電腦,看到各種各樣的Web前端頁面。你知道他們是如何製作的嗎?為了讓頁面更具有規範性,讓使用者更加方便,在製作頁面過程中必須遵循一定的設計流程。在這裡就為大家詳細介紹一下製作一個Web前端頁面的設計流程及註意事項。 一:確定網站主題 每個網站都有自身以及對用戶的定位。針對網站定位確定網站 ...
  • 大學畢業一年收穫還是滿滿的!手動滑稽 今天呢,來記錄一個爬蟲項目,用的web-magic實現,不說Java和Python那個更強,只看那個代價更小,與現在我而言自然是Java嘍!同時呢magic也是參考了Scrapy框架的。 先把git地址掏出來:https://gitee.com/xxxx/mag ...
  • 導讀 模板模式在是Spring底層被廣泛的應用,比如事務管理器的實現,JDBC模板的實現。 文章首發於作者的微信公眾號【碼猿技術專欄】 今天就來談談「什麼是模板模式」、「模板模式的優缺點」、「模板模式的簡單演示」、「模板模式在Spring底層的實現」。 什麼是模板模式 模板模式首先要有一個抽象類,這 ...
  • 定義: 原型模式(Prototype):用原型實例指定創建對象的種類,並且通過 clone 這些原型創建新的對象。原型模式其實就是從一個對象再創建另外一個可定製的對象,而且不需要知道任何創建的細節。目的是使用 clone 對象來減少 new 對象的開銷。 原型 clone 有淺複製和深複製:淺複製: ...
  • 前言 本文僅是對以前寫的小示例進行一次梳理,由於本人菜鳥一枚,後端代碼寫的很渣,前端頁面也不好看,還請大家多多海涵。 一、程式簡介 程式分為cmdb_server,cmdb_client兩部分,以運維為核心開發的簡易框架,cmdb_client主要負責資產信息採集,採集到數據後將數據進行清洗,彙總. ...
  • 我們都知道以 結尾的 Java 源文件,經過編譯之後會變成 結尾的位元組碼文件。JVM 通過類載入器來載入位元組碼文件,然後再執行程式。 什麼時候載入一個類 那麼, 什麼時候類載入器會載入一個類呢? 用到這個類的時候,JVM的類載入器就會載入這個類。用到這兩個字說起來很抽象,我用代碼和圖例來說明。 有下 ...
  • 趁節假日,順便整理了舊資料,發現了老外寫的一本書、清華大學出版社翻譯(2002就出版了)。 相當於2002年時就已經籌劃寫開源中間件了。 這麼多年過去,java框架、中間件也都寫的差不多了,舉例如下(只舉特別): web application server:tomcat web framework ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...