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
  • Timer是什麼 Timer 是一種用於創建定期粒度行為的機制。 與標準的 .NET System.Threading.Timer 類相似,Orleans 的 Timer 允許在一段時間後執行特定的操作,或者在特定的時間間隔內重覆執行操作。 它在分散式系統中具有重要作用,特別是在處理需要周期性執行的 ...
  • 前言 相信很多做WPF開發的小伙伴都遇到過表格類的需求,雖然現有的Grid控制項也能實現,但是使用起來的體驗感並不好,比如要實現一個Excel中的表格效果,估計你能想到的第一個方法就是套Border控制項,用這種方法你需要控制每個Border的邊框,並且在一堆Bordr中找到Grid.Row,Grid. ...
  • .NET C#程式啟動閃退,目錄導致的問題 這是第2次踩這個坑了,很小的編程細節,容易忽略,所以寫個博客,分享給大家。 1.第一次坑:是windows 系統把程式運行成服務,找不到配置文件,原因是以服務運行它的工作目錄是在C:\Windows\System32 2.本次坑:WPF桌面程式通過註冊表設 ...
  • 在分散式系統中,數據的持久化是至關重要的一環。 Orleans 7 引入了強大的持久化功能,使得在分散式環境下管理數據變得更加輕鬆和可靠。 本文將介紹什麼是 Orleans 7 的持久化,如何設置它以及相應的代碼示例。 什麼是 Orleans 7 的持久化? Orleans 7 的持久化是指將 Or ...
  • 前言 .NET Feature Management 是一個用於管理應用程式功能的庫,它可以幫助開發人員在應用程式中輕鬆地添加、移除和管理功能。使用 Feature Management,開發人員可以根據不同用戶、環境或其他條件來動態地控制應用程式中的功能。這使得開發人員可以更靈活地管理應用程式的功 ...
  • 在 WPF 應用程式中,拖放操作是實現用戶交互的重要組成部分。通過拖放操作,用戶可以輕鬆地將數據從一個位置移動到另一個位置,或者將控制項從一個容器移動到另一個容器。然而,WPF 中預設的拖放操作可能並不是那麼好用。為瞭解決這個問題,我們可以自定義一個 Panel 來實現更簡單的拖拽操作。 自定義 Pa ...
  • 在實際使用中,由於涉及到不同編程語言之間互相調用,導致C++ 中的OpenCV與C#中的OpenCvSharp 圖像數據在不同編程語言之間難以有效傳遞。在本文中我們將結合OpenCvSharp源碼實現原理,探究兩種數據之間的通信方式。 ...
  • 一、前言 這是一篇搭建許可權管理系統的系列文章。 隨著網路的發展,信息安全對應任何企業來說都越發的重要,而本系列文章將和大家一起一步一步搭建一個全新的許可權管理系統。 說明:由於搭建一個全新的項目過於繁瑣,所有作者將挑選核心代碼和核心思路進行分享。 二、技術選擇 三、開始設計 1、自主搭建vue前端和. ...
  • Csharper中的表達式樹 這節課來瞭解一下表示式樹是什麼? 在C#中,表達式樹是一種數據結構,它可以表示一些代碼塊,如Lambda表達式或查詢表達式。表達式樹使你能夠查看和操作數據,就像你可以查看和操作代碼一樣。它們通常用於創建動態查詢和解析表達式。 一、認識表達式樹 為什麼要這樣說?它和委托有 ...
  • 在使用Django等框架來操作MySQL時,實際上底層還是通過Python來操作的,首先需要安裝一個驅動程式,在Python3中,驅動程式有多種選擇,比如有pymysql以及mysqlclient等。使用pip命令安裝mysqlclient失敗應如何解決? 安裝的python版本說明 機器同時安裝了 ...