Dbs封裝_連接池

1.Dbs封裝

每一個數據庫都對應著一個dao 每個dao勢必存在公共部分 我們需要將公共部分抽取出來 封裝成一個工具類 保留個性化代碼即可

  • 我們的工具類一般命名為xxxs 比如Strings 就是字符串相關的工具類 而工具類 我們將其放置于util包中
  • 我們以是否有<T>區分泛型方法和非泛型方法
  • 建議先創建語句、傳遞參數之后 在執行語句 即不要著急將ResultSet放置在try-with-resources中
  • 你可以通過live template快速生成一些代碼模板 比如itar可以幫助我們快速生成遍歷數組元素的模板 我們也可以自定義動態模板
  • dao中需要傳遞一段個性化代碼(即ResultSet->bean)給dbs 要求dbs存在一個接口(用于將數據庫中每一行ResultSet映射為bean)用于接收代碼 同時可以設置一個row 用于顯示當前所在的行號(數據庫中的行號一般從0開始計數 列號一般從1開始計數)
  • 既然存在dbs 那么以前的三個常量URL、USERNAME、PASSWORD就可以作為公共部分存放在dbs中
  • 代碼實現
    • Dbs.java
    package com.axihh.util;import com.axihh.Constants;import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.util.ArrayList;
    import java.util.List;public class Dbs {// 常量public static final String URL = "jdbc:mysql://localhost:3306/crm?serverTimezone=UTC";public static final String USERNAME = "root";public static final String PASSWORD = "root";// 定義一個方法 用于存放數據庫保存的公共代碼public static boolean update(String sql, Object ...args) {try {// 注冊驅動Class.forName("com.mysql.cj.jdbc.Driver");try(Connection conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);PreparedStatement pstmt = conn.prepareStatement(sql)) {// 設置參數for (int i = 0; i < args.length; i++) {pstmt.setObject(i + 1, args[i]);}// 執行sql語句return pstmt.executeUpdate() > 0;}}catch(Exception e) {e.printStackTrace();// 執行到此 說明沒有任何行受到影響return false;}}// 定義一個方法 用于存放用戶信息集合獲取的公共代碼public static <T> List<T> list(String sql, RowMapper<T> rm, Object ...args) {try {// 注冊驅動Class.forName("com.mysql.cj.jdbc.Driver");try(Connection conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);PreparedStatement pstmt = conn.prepareStatement(sql)) {// 建議不要將resultset寫入try-with-resources中 因為我們要保持順序的先后性 先創建語句 在執行語句 保持這樣的順序// 設置參數for (int i = 0; i < args.length; i++) {pstmt.setObject(i + 1, args[i]);}// 執行sql語句ResultSet rs = pstmt.executeQuery();List<T> array = new ArrayList<>();// resultset映射beanfor(int row = 0; rs.next(); row++) {array.add(rm.map(rs, row));}return array;}}catch(Exception e) {e.printStackTrace();// 如果出現異常 證明返回值為空return null;}}// 定義一個接口 用于接收resultset映射bean的代碼 具體就是數據庫中的每一行對應的resultset映射為beanpublic interface RowMapper<T> {public T map(ResultSet rs, int row) throws Exception;}
    }
    
    • CustomerDao.java
    package com.axihh.dao;import com.axihh.bean.Customer;
    import com.axihh.util.Dbs;import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import com.axihh.util.Dbs.RowMapper;
    import java.util.List;public class CustomerDao {public boolean save(Customer customer){String sql = "INSERT INTO customer(name, age, height) VALUES (?, ?, ?)";return Dbs.update(sql, customer.getName(), customer.getAge(), customer.getHeight());}public List<Customer> list() {String sql = "SELECT id, name, age, height FROM customer";return Dbs.list(sql, (rs, row) -> {Customer customer = new Customer();customer.setId(rs.getInt("id"));customer.setName(rs.getString("name"));customer.setAge(rs.getInt("age"));customer.setHeight(rs.getDouble("height"));System.out.println(row + "_" + customer);return customer;});}
    }
    

2.缺陷

雖然 我們將dao的公共代碼抽取到dbs中以期簡化了dao 但是仍然存在著一些問題 常量(比如PASSWORD)動態修改時 需要打開源碼修改 再重新編譯打包 顯然很麻煩

  • 解決方案:利用配置文件幫助我們將一些需要動態修改的值放入配置文件中 以代替在寫死的Java代碼

1.配置文件

  • 常見的配置文件
    • properties:比較單一 適合量小、簡單的配置
      • key、value的分隔符是=、:
      • 建議分隔符左右不要留空格
      • #、!開頭是單行注釋
      • 可以用\來連接多行內容(內容太多一行中無法顯示)
    • xml:比較靈活 適合量大、復雜的配置

2.properties解決方案

  • 首先新建一個properties文件 具體就是在src下右鍵選擇resource bundle
  • 編寫properties內容 以鍵值對的形式定義三個動態修改的變量(不包含任何的修飾符和字符串雙引號 僅僅只是鍵和值)
    在這里插入圖片描述
  • 讀取properties內容 根據鍵找值的方式獲取相關值寫入Dbs中對應的變量 由于變量支持動態修改 所以不在通過final修飾 并且變量不再是常量 所以無需大寫
    • 我們將讀取properties 寫入三個動態修改的變量代碼內置于靜態初始化塊中 表明程序運行過程中僅需進行一次賦值
    • 調用class獲取當前類的字節碼文件 然后通過getClassLoader獲取加載該字節碼文件的類加載器 然后通過getResourceAsStream獲取資源文件 并且通過字節輸入流讀取該資源文件
    • 定義Properties對象 將資源文件加載到該對象中
    • 通過鍵找值的方式 完成對Dbs文件中三個動態修改變量的賦值操作
    • 注意 其中InputStream屬于資源 需要關閉以釋放 通過try-with-resources將其自動關閉
package com.axihh.util;import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;public class Dbs {// 常量public static String url;public static String username;public static String password;static {try(// 通過當前類獲取字節碼文件 然后通過字節碼文件獲取類加載器 然后通過類加載器獲取資源文件 并且通過字節輸入流讀取該資源文件InputStream is = Dbs.class.getClassLoader().getResourceAsStream("db.properties")) {// 創建properties對象 然后將字節輸入流讀取的內容加載進該對象中Properties properties = new Properties();properties.load(is);// 然后通過鍵找值的方式獲取指定變量對應的值url = properties.getProperty("url");username = properties.getProperty("username");password = properties.getProperty("password");} catch (IOException e) {e.printStackTrace();}}// 定義一個方法 用于存放數據庫保存的公共代碼public static boolean update(String sql, Object ...args) {try {// 注冊驅動Class.forName("com.mysql.cj.jdbc.Driver");try(Connection conn = DriverManager.getConnection(url, username, password);PreparedStatement pstmt = conn.prepareStatement(sql)) {// 設置參數for (int i = 0; i < args.length; i++) {pstmt.setObject(i + 1, args[i]);}// 執行sql語句return pstmt.executeUpdate() > 0;}}catch(Exception e) {e.printStackTrace();// 執行到此 說明沒有任何行受到影響return false;}}// 定義一個方法 用于存放用戶信息集合獲取的公共代碼public static <T> List<T> list(String sql, RowMapper<T> rm, Object ...args) {try {// 注冊驅動Class.forName("com.mysql.cj.jdbc.Driver");try(Connection conn = DriverManager.getConnection(url, username, password);PreparedStatement pstmt = conn.prepareStatement(sql)) {// 建議不要將resultset寫入try-with-resources中 因為我們要保持順序的先后性 先創建語句 在執行語句 保持這樣的順序// 設置參數for (int i = 0; i < args.length; i++) {pstmt.setObject(i + 1, args[i]);}// 執行sql語句ResultSet rs = pstmt.executeQuery();List<T> array = new ArrayList<>();// resultset映射beanfor(int row = 0; rs.next(); row++) {array.add(rm.map(rs, row));}return array;}}catch(Exception e) {e.printStackTrace();// 如果出現異常 證明返回值為空return null;}}// 定義一個接口 用于接收resultset映射bean的代碼 具體就是數據庫中的每一行對應的resultset映射為beanpublic interface RowMapper<T> {public T map(ResultSet rs, int row) throws Exception;}
}
  • 細節

我們將properties文件創建在src中 目的在于經過編譯打包這一系列操作之后 該資源文件被內置于classes目錄中 經過查詢 可知該目錄中正好是存放src下字節碼文件的位置 類加載器將字節碼文件加載到JVM中 前提肯定是知道classes目錄的位置 那么我們就可以利用這一點通過類加載器找到classes中的properties文件

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/15933.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/15933.shtml
英文地址,請注明出處:http://en.pswp.cn/web/15933.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Python并發編程學習記錄

1、初識并發編程 1.1、串行&#xff0c;并行&#xff0c;并發 串行(serial)&#xff1a;一個cpu上按順序完成多個任務&#xff1b; 并行(parallelism)&#xff1a;任務數小于或等于cup核數&#xff0c;多個任務是同時執行的&#xff1b; 并發(concurrency)&#xff1a;一個…

計算機SCI期刊,IF=8+,專業性強,潛力新刊!

一、期刊名稱 Journal of Big data 二、期刊簡介概況 期刊類型&#xff1a;SCI 學科領域&#xff1a;計算機科學 影響因子&#xff1a;8.1 中科院分區&#xff1a;2區 出版方式&#xff1a;開放出版 版面費&#xff1a;$1990 三、期刊征稿范圍 《大數據雜志》發表了關于…

2024年【T電梯修理】考試內容及T電梯修理新版試題

題庫來源&#xff1a;安全生產模擬考試一點通公眾號小程序 2024年【T電梯修理】考試內容及T電梯修理新版試題&#xff0c;包含T電梯修理考試內容答案和解析及T電梯修理新版試題練習。安全生產模擬考試一點通結合國家T電梯修理考試最新大綱及T電梯修理考試真題匯總&#xff0c;…

線性dp合集,藍橋杯

貿易航線 0貿易航線 - 藍橋云課 (lanqiao.cn) n,m,kmap(int ,input().split()) #貪心的想&#xff0c;如果買某個東西利潤最大&#xff0c;那我肯定直接拉滿啊&#xff0c;所以買k個和買一個沒區別 p[0] for i in range(n):p.append([-1]list(map(int,input().split())))dp[[…

(2024,SDE,對抗薛定諤橋匹配,離散時間迭代馬爾可夫擬合,去噪擴散 GAN)

Adversarial Schrdinger Bridge Matching 公眾號&#xff1a;EDPJ&#xff08;進 Q 交流群&#xff1a;922230617 或加 VX&#xff1a;CV_EDPJ 進 V 交流群&#xff09; 目錄 0. 摘要 1. 簡介 4. 實驗 0. 摘要 薛定諤橋&#xff08;Schrdinger Bridge&#xff0c;SB&…

el-autocomplete后臺遠程搜索

el-complete可以實現后臺遠程搜索功能&#xff0c;但有時傳入數據為空時&#xff0c;接口可能會報錯。此時可在querySearchAsync方法中&#xff0c;根據queryString判斷&#xff0c;若為空&#xff0c;則不掉用接口&#xff0c;直接callback([])&#xff0c;反之則調用接口&…

浮點型比較大小

浮點數的存儲形式 浮點數按照在內存中所占字節數和數值范圍&#xff0c;可以分為浮點型&#xff0c;雙精度浮點型和長雙浮點型數。 代碼&#xff1a; printf("lgn:%e \n", pow(exp(1), 100));printf("lgn:%f ", pow(exp(1), 100));輸出結果&#xff1a; …

Stanford斯坦福 CS 224R: 深度強化學習 (5)

離線強化學習:第一部分 強化學習(RL)旨在讓智能體通過與環境交互來學習最優策略,從而最大化累積獎勵。傳統的RL訓練都是在線(online)進行的,即智能體在訓練過程中不斷與環境交互,實時生成新的狀態-動作數據,并基于新數據來更新策略。這種在線學習雖然簡單直觀,但也存在一些局限…

【Could not find Chrome This can occur if either】

爬蟲練習中遇到的問題 使用puppeteer執行是提示一下錯誤 Error: Could not find Chrome (ver. 125.0.6422.78). This can occur if either you did not perform an installation before running the script (e.g. npx puppeteer browsers install chrome) oryour cache path…

CLIP 論文的關鍵內容

CLIP 論文整體架構 該論文總共有 48 頁&#xff0c;除去最后的補充材料十頁去掉&#xff0c;正文也還有三十多頁&#xff0c;其中大部分篇幅都留給了實驗和響應的一些分析。 從頭開始的話&#xff0c;第一頁就是摘要&#xff0c;接下來一頁多是引言&#xff0c;接下來的兩頁就…

常用 CSS 寫法

不是最后一個 :not(:last-child)漸變色 background: linear-gradient(270deg, #15aaff 0%, #02396a 100%);文字漸變色 background-image: linear-gradient(to right, #ff7e5f, #feb47b); -webkit-background-clip: text; background-clip: text; color: transparent;

python文件IO基礎知識

目錄 1.open函數打開文件 2.文件對象讀寫數據和關閉 3.文本文件和二進制文件的區別 4.編碼和解碼 讀寫文本文件時 讀寫二進制文件時 5.文件指針位置 6.文件緩存區與flush()方法 1.open函數打開文件 使用 open 函數創建一個文件對象&#xff0c;read 方法來讀取數據&…

談談磁盤的那些操作

磁盤格式化 是指把一張空白的盤劃分成一個個小區域并編號&#xff0c;以供計算機存儲和讀取數據。格式化是一種純物理操作&#xff0c;是在磁盤的所有數據區上寫零的操作過程&#xff0c;同時對硬盤介質做一致性檢測&#xff0c;并且標記出不可讀和壞的扇區。由于大部分硬盤在…

電子技術學習路線

在小破站上看到大佬李皆寧的技術路線分析&#xff0c;再結合自己這幾年的工作。發現的確是這樣&#xff0c;跟著大佬的技術路線去學習是會輕松很多&#xff0c;現在想想&#xff0c;這路線其實跟大學四年的學習順序是很像的。 本期記錄學習路線&#xff0c;方便日后查看。 傳統…

python 深度圖生成點云(方法二)

深度圖生成點云 一、介紹1.1 概念1.2 思路1.3 函數講解二、代碼示例三、結果示例接上篇:深度圖生成點云(方法1) 一、介紹 1.1 概念 深度圖生成點云:根據深度圖像(depth image)和相機內參(camera intrinsics)生成點云(PointCloud)。 1.2 思路 點云坐標的計算公式如…

pillow學習7

繪制驗證碼 from PIL import Image,ImageFilter,ImageFont,ImageDraw import random width100 hight100 imImage.new(RGB,(width,hight),(255,255,255)) drawImageDraw.Draw(im) #獲取顏色 def get_color1():return (random.randint(200, 255), random.randint(200, 255), ran…

京東Java社招面試題真題,最新面試題

Java中接口與抽象類的區別是什么&#xff1f; 1、定義方式&#xff1a; 接口是完全抽象的&#xff0c;只能定義抽象方法和常量&#xff0c;不能有實現&#xff1b;而抽象類可以有抽象方法和具體實現的方法&#xff0c;也可以定義成員變量。 2、實現與繼承&#xff1a; 一個類…

幾種常用的配置文件格式對比分析——ini、json、xml、toml、yaml

配置文件用于存儲軟件程序的配置信息&#xff0c;以便程序能夠根據這些信息進行自定義和調整。常用的配置文件格式包括INI、XML、JSON和YAML。下面對它們進行簡單介紹&#xff0c;并分析各自的優缺點。 1. INI 文件格式 簡介&#xff1a; INI&#xff08;Initialization&…

FPGA之tcp/udp

在調試以太網的過程中&#xff0c;考慮了vivado IP配置(管腳、reset等)&#xff0c;SDK中PHY芯片的配置(芯片地址、自適應速率配置等)&#xff0c;但是&#xff0c;唯獨忽略了tcp/udp協議&#xff0c;所以在ping通之后仍無法連接。 所以現在來學習一下tcp與udp的區別 ---- 為什…

經典面試題:進程、線程、協程開銷問題,為什么進程切換的開銷比線程的大?

上下文切換的過程&#xff1f; 上下文切換是操作系統在將CPU從一個進程切換到另一個進程時所執行的過程。它涉及保存當前執行進程的狀態并加載下一個將要執行的進程的狀態。下面是上下文切換的詳細過程&#xff1a; 保存當前進程的上下文&#xff1a; 當操作系統決定切換到另…