【保姆級喂飯教程】python基于mysql-connector-python的數據庫操作通用封裝類(連接池版)

目錄

  • 項目環境
  • 一、db_config.py
  • 二、mysql_executor.py
  • 三、test/main.py

在使用mysql-connector-python連接MySQL數據庫的時候,如同Java中的jdbc一般,每條sql需要創建和刪除連接,很自然就想到寫一個抽象方法,但是找了找沒有官方標準的,或者使用SQLAlchemy等類似的orm框架,于是調試deepseek寫了一個

項目背景:【保姆級喂飯教程】uv教程一文講透:安裝,創建,配置,工具,命令

項目環境

安裝庫,
【沉浸式解決問題】mysql-connector-python連接數據庫:RuntimeError: Failed raising error.

uv add mysql-connector-python==8.0.33

在這里插入圖片描述

目錄,init文件為空
在這里插入圖片描述

一、db_config.py


class DBConfig:"""數據庫配置基類"""@classmethoddef get_config(cls, name: str) -> dict:"""獲取指定數據庫配置"""return getattr(cls, name).valueclass MySQLConfig(DBConfig):"""MySQL數據庫配置"""# 基礎配置模板BASE = {"pool_name": "mysql_pool","pool_size": 10,"pool_reset_session": True,"charset": "utf8mb4","autocommit": False}# 具體數據庫實例配置PYTHON_DB = {**BASE,"host": "127.0.0.1","port": 3306,"user": "python","password": "python","database": "test-python"}LOG_DB = {**BASE,"host": "log-db.example.com","port": 3307,"user": "log_user","password": "log_password","database": "app_logs"}

二、mysql_executor.py

"""
MySQL 數據庫連接池執行器
提供安全、高效的數據庫操作接口,支持連接池、事務管理和批量操作
"""from mysql.connector import pooling, Error
from typing import Union, List, Tuple, Dict, Anyclass MySQLExecutor:"""MySQL 數據庫操作通用封裝類(連接池版)特性:1. 基于連接池實現高效連接管理2. 支持自動和手動事務控制3. 提供查詢、執行、批量操作等多種方法4. 完善的異常處理和資源管理5. 詳細的日志記錄使用示例:with MySQLExecutor(config) as executor:# 執行查詢results = executor.query("SELECT * FROM users WHERE age > %s", (25,))# 執行寫入操作executor.execute("UPDATE users SET status = 'active' WHERE id = %s", (1,))# 批量操作executor.batch_execute("INSERT INTO logs (message) VALUES (%s)", [('log1',), ('log2',)])"""def __init__(self, config: Dict[str, Any]):"""初始化數據庫執行器參數:config: 數據庫配置字典,必須包含連接池相關參數示例:{"pool_name": "mysql_pool","pool_size": 10,"host": "127.0.0.1","port": 3306,"user": "root","password": "password","database": "test_db"}異常:ConnectionError: 如果連接池創建失敗"""self.config = configself.pool = self._create_pool()self.active_connection = None  # 當前活動連接(用于事務)def _create_pool(self) -> pooling.MySQLConnectionPool:"""創建數據庫連接池返回:pooling.MySQLConnectionPool: MySQL連接池實例異常:ConnectionError: 如果連接池創建失敗"""try:print(f"正在創建MySQL連接池: {self.config.get('pool_name', 'unnamed_pool')}")return pooling.MySQLConnectionPool(**self.config)except Error as e:error_msg = f"創建MySQL連接池失敗: {e}"print(error_msg)raise ConnectionError(error_msg) from edef __enter__(self):"""支持with上下文管理返回執行器實例本身"""return selfdef __exit__(self, exc_type, exc_val, exc_tb):"""退出上下文時自動關閉活動連接"""self.close_active_connection()def connection(self):"""返回一個連接上下文管理器使用示例:with executor.connection() as conn:with conn.cursor() as cursor:cursor.execute("SELECT * FROM table")results = cursor.fetchall()"""return self._ConnectionContext(self)class _ConnectionContext:"""連接上下文管理器內部類用于自動管理連接的獲取和釋放"""def __init__(self, executor):self.executor = executorself.conn = Nonedef __enter__(self) -> pooling.PooledMySQLConnection:"""進入上下文時從連接池獲取連接"""try:self.conn = self.executor.get_connection()return self.connexcept Error as e:error_msg = f"獲取數據庫連接失敗: {e}"print(error_msg)raise ConnectionError(error_msg) from edef __exit__(self, exc_type, exc_val, exc_tb):"""退出上下文時關閉連接"""if self.conn and self.conn.is_connected():try:self.conn.close()except Error as e:print(f"關閉數據庫連接時出錯: {e}")def get_connection(self) -> pooling.PooledMySQLConnection:"""從連接池獲取一個新的數據庫連接返回:pooling.PooledMySQLConnection: 數據庫連接對象注意:使用后需要手動關閉連接,推薦使用connection()上下文管理器"""return self.pool.get_connection()def close_active_connection(self):"""關閉當前活動連接(如果存在)主要用于清理事務連接"""if self.active_connection and self.active_connection.is_connected():try:self.active_connection.close()self.active_connection = Noneexcept Error as e:print(f"關閉活動連接時出錯: {e}")def start_transaction(self):"""開始一個新的事務異常:ConnectionError: 如果獲取連接失敗"""try:if not self.active_connection or not self.active_connection.is_connected():self.active_connection = self.get_connection()self.active_connection.start_transaction()print("事務已開始")except Error as e:error_msg = f"開始事務失敗: {e}"print(error_msg)raise ConnectionError(error_msg) from edef commit(self):"""提交當前事務并關閉活動連接異常:ConnectionError: 如果提交失敗或沒有活動事務"""if not self.active_connection:print("警告: 嘗試提交但無活動事務")returntry:self.active_connection.commit()print("事務已提交")except Error as e:error_msg = f"提交事務失敗: {e}"print(error_msg)raise ConnectionError(error_msg) from efinally:self.close_active_connection()def rollback(self):"""回滾當前事務并關閉活動連接異常:ConnectionError: 如果回滾失敗"""if not self.active_connection:print("警告: 嘗試回滾但無活動事務")returntry:self.active_connection.rollback()print("事務已回滾")except Error as e:error_msg = f"回滾事務失敗: {e}"print(error_msg)raise ConnectionError(error_msg) from efinally:self.close_active_connection()def query(self,sql: str,params: Union[Tuple, List, None] = None,dictionary: bool = False) -> Union[List[Tuple], List[Dict]]:"""執行查詢語句(SELECT)參數:sql: SQL查詢語句params: 查詢參數(可選)dictionary: 是否返回字典格式結果(默認為元組)返回:查詢結果列表(元組或字典格式)異常:DatabaseError: 如果查詢執行失敗"""try:with self.connection() as conn:with conn.cursor(dictionary=dictionary) as cursor:cursor.execute(sql, params)return cursor.fetchall()except Error as e:error_msg = f"查詢執行失敗: {e}\nSQL: {sql}\n參數: {params}"print(error_msg)raise DatabaseError(error_msg) from edef execute(self,sql: str,params: Union[Tuple, List, None] = None,commit: bool = True) -> int:"""執行非查詢語句(INSERT/UPDATE/DELETE)參數:sql: SQL操作語句params: 操作參數(可選)commit: 是否自動提交事務(默認為True)返回:受影響的行數異常:DatabaseError: 如果操作執行失敗"""try:with self.connection() as conn:with conn.cursor() as cursor:cursor.execute(sql, params)affected_rows = cursor.rowcountif commit:conn.commit()return affected_rowsexcept Error as e:error_msg = f"操作執行失敗: {e}\nSQL: {sql}\n參數: {params}"print(error_msg)raise DatabaseError(error_msg) from edef batch_execute(self,sql: str,params_list: List[Union[Tuple, List]],commit: bool = True) -> int:"""批量執行操作(高效)參數:sql: SQL操作語句params_list: 參數列表commit: 是否提交事務(默認為True)返回:受影響的總行數異常:DatabaseError: 如果批量操作失敗ValueError: 如果參數列表為空"""if not params_list:raise ValueError("參數列表不能為空")try:with self.connection() as conn:with conn.cursor() as cursor:cursor.executemany(sql, params_list)affected_rows = cursor.rowcountif commit:conn.commit()return affected_rowsexcept Error as e:error_msg = f"批量操作失敗: {e}\nSQL: {sql}\n參數數量: {len(params_list)}"print(error_msg)# 嘗試回滾事務try:if conn and conn.is_connected():conn.rollback()except Error as rollback_err:print(f"回滾批量操作失敗: {rollback_err}")raise DatabaseError(error_msg) from edef execute_many(self,sql_commands: List[str],params_list: List[Union[Tuple, List, None]] = None,commit: bool = True) -> int:"""執行多個SQL命令(可包含不同操作)參數:sql_commands: SQL命令列表params_list: 參數列表(可選,默認為None)commit: 是否提交事務(默認為True)返回:受影響的總行數異常:DatabaseError: 如果執行失敗ValueError: 如果命令和參數長度不匹配"""if params_list is None:params_list = [None] * len(sql_commands)if len(sql_commands) != len(params_list):raise ValueError(f"SQL命令({len(sql_commands)})和參數列表({len(params_list)})長度不一致")try:with self.connection() as conn:with conn.cursor() as cursor:total_affected = 0for i, (sql, params) in enumerate(zip(sql_commands, params_list)):try:cursor.execute(sql, params)total_affected += cursor.rowcountexcept Error as e:# 記錄具體哪個命令失敗error_msg = f"執行第 {i + 1} 條命令失敗: {e}\nSQL: {sql}\n參數: {params}"print(error_msg)raise DatabaseError(error_msg) from eif commit:conn.commit()return total_affectedexcept Error as e:# 回滾整個事務try:if conn and conn.is_connected():conn.rollback()except Error as rollback_err:print(f"回滾操作失敗: {rollback_err}")raise DatabaseError(f"多命令執行失敗: {e}") from e# 自定義異常類,提供更清晰的錯誤分類
class DatabaseError(Exception):"""數據庫操作異常基類"""passclass ConnectionError(DatabaseError):"""數據庫連接相關異常"""pass

三、test/main.py

from mysql.db_config import MySQLConfig
from mysql.mysql_executor import MySQLExecutor, ConnectionError, DatabaseError# 獲取數據庫配置
db_config = MySQLConfig.get_config("PYTHON_DB")try:# 創建執行器(使用with上下文確保資源清理)with MySQLExecutor(db_config) as executor:print("=" * 50)print("示例1: 基本查詢")print("=" * 50)try:# 執行查詢 - 返回字典格式結果users = executor.query("SELECT * FROM users WHERE age > %s",(25,),dictionary=True)print(f"查詢成功,獲取到 {len(users)} 條記錄")if users:print(f"第一條記錄: {users[0]}")except DatabaseError as e:print(f"查詢操作失敗: {e}")# 在實際應用中,這里可以記錄日志或執行恢復操作print("\n" + "=" * 50)print("示例2: 插入數據")print("=" * 50)try:# 插入新用戶new_user = ("Alice", "alice@example.com", 30)insert_sql = "INSERT INTO users (name, email, age) VALUES (%s, %s, %s)"affected = executor.execute(insert_sql, new_user)print(f"插入成功,影響行數: {affected}")except DatabaseError as e:print(f"插入操作失敗: {e}")print("\n" + "=" * 50)print("示例3: 批量插入")print("=" * 50)try:# 批量插入用戶users_data = [("Bob", "bob@example.com", 28),("Charlie", "charlie@example.com", 35),("David", "david@example.com", 42)]insert_sql = "INSERT INTO users (name, email, age) VALUES (%s, %s, %s)"# 批量執行batch_affected = executor.batch_execute(insert_sql, users_data)print(f"批量插入成功,總影響行數: {batch_affected}")except (DatabaseError, ValueError) as e:print(f"批量插入失敗: {e}")print("\n" + "=" * 50)print("示例4: 事務處理")print("=" * 50)try:# 開始事務executor.start_transaction()print("事務已開始")try:# 事務內操作1:更新用戶update_sql = "UPDATE users SET age = %s WHERE id = %s"executor.execute(update_sql, (31, 1), commit=False)print("用戶更新成功")# 事務內操作2:插入日志log_sql = "INSERT INTO activity_log (user_id, action) VALUES (%s, %s)"executor.execute(log_sql, (1, "age_update"), commit=False)print("日志插入成功")# 查詢事務內數據user_data = executor.query("SELECT * FROM users WHERE id = %s",(1,),dictionary=True)print(f"事務內用戶數據: {user_data}")# 提交事務executor.commit()print("事務操作成功完成")except DatabaseError as e:# 事務內部操作失敗,回滾事務print(f"事務內操作失敗: {e}")executor.rollback()print("已回滾事務")raise  # 繼續向上拋出異常except (DatabaseError, ConnectionError) as e:print(f"事務處理失敗: {e}")print("\n" + "=" * 50)print("示例5: 復雜操作(多個SQL命令)")print("=" * 50)try:# 轉賬操作(多個SQL命令)sql_commands = ["UPDATE accounts SET balance = balance - 100 WHERE id = 1","UPDATE accounts SET balance = balance + 100 WHERE id = 2","INSERT INTO transactions (from_acc, to_acc, amount) VALUES (1, 2, 100)"]# 執行多個命令total_affected = executor.execute_many(sql_commands)print(f"轉賬操作完成,總影響行數: {total_affected}")except (DatabaseError, ValueError) as e:print(f"多命令執行失敗: {e}")print("\n" + "=" * 50)print("示例6: 直接使用連接上下文")print("=" * 50)try:# 直接使用連接上下文with executor.connection() as conn:with conn.cursor(dictionary=True) as cursor:cursor.execute("SELECT * FROM users WHERE status = 'active'")active_users = cursor.fetchall()print(f"活躍用戶數量: {len(active_users)}")# 同一個連接中執行另一個操作with conn.cursor() as cursor:cursor.execute("UPDATE users SET last_login = NOW() WHERE status = 'active'")conn.commit()print(f"更新了 {cursor.rowcount} 個用戶的登錄時間")except (ConnectionError, DatabaseError) as e:print(f"連接上下文操作失敗: {e}")except ConnectionError as e:print(f"數據庫連接初始化失敗: {e}")# 在實際應用中,這里應該進行更嚴格的錯誤處理
finally:print("所有數據庫操作完成")

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

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

相關文章

【MCP服務】藍耘元生代 | 藍耘MCP平臺來襲!DeepSeek MCP服務器玩轉大模型集成

【作者主頁】Francek Chen 【專欄介紹】???人工智能與大模型應用??? 人工智能(AI)通過算法模擬人類智能,利用機器學習、深度學習等技術驅動醫療、金融等領域的智能化。大模型是千億參數的深度神經網絡(如ChatGPT&#xff09…

Spring Boot 整合 Minio 實現高效文件存儲解決方案(本地和線上)

文章目錄前言一、配置1.配置文件:application.yml2.配置類:MinioProperties3.工具類:MinioUtil3.1 初始化方法3.2 核心功能3.3 關鍵技術點二、使用示例1.控制器類:FileController2.服務類3.效果展示總結前言 Minio 是一個高性能的…

【Unity3D實例-功能-鏡頭】第三人稱視覺-鏡頭優化

這一篇我們一起來調整一下Cinemachine的第三人稱視覺的鏡頭設置。一般用于ARPG角色扮演游戲的場景中。Unity里頭,這種視角簡直就是標配。來吧,咱們一起研究研究怎么調出這種視角效果!目錄:1.調整虛擬攝像機的Y軸2.調整虛擬攝像機的…

二叉樹算法之【中序遍歷】

目錄 LeetCode-94題 LeetCode-94題 給定一個二叉樹的根節點root&#xff0c;返回它的中序遍歷結果。 class Solution {public List<Integer> inorderTraversal(TreeNode root) {List<Integer> result new ArrayList<>();order(root, result);return res…

Android14的QS面板的加載解析

/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java QS 面板的創建 getNotificationShadeWindowView()&#xff1a;整個systemui的最頂級的視圖容器&#xff08;super_notification_shade.xml&#xff09;R.id.qs_frame &…

解鎖webpack核心技能(二):配置文件和devtool配置指南

一、配置文件webpack 提供的 cli 支持很多的參數&#xff0c;例如 --mode 。在我們平時的開發過程中&#xff0c;我們要學習很多的功能&#xff0c;這些很多都是可以用參數來完成的。那么后邊就會導致參數越來越多&#xff0c;我們使用命令特別的不方便&#xff0c;所以我們會使…

Gitlab+Jenkins+K8S+Registry 建立 CI/CD 流水線

一、前言 DevOps是一種將開發&#xff08;Development&#xff09;和運維&#xff08;Operations&#xff09;相結合的軟件開發方法論。它通過自動化和持續交付的方式&#xff0c;將軟件開發、測試和部署等環節緊密集成&#xff0c;以提高效率和產品質量。在本篇博客中&#xf…

【Linux】特效爆滿的Vim的配置方法 and make/Makefile原理

一、軟件包管理器 1、Linux下安裝軟件的常見方式&#xff1a; 1&#xff09;源代碼安裝——不推薦。 2&#xff09;rpm包安裝——不推薦。 3&#xff09;包管理器安裝——推薦 2、安裝軟件命令 # Centos$ sudo yum install -y lrzsz# Ubuntu$ sudo apt install -y lrzsz 3、卸…

Spring Boot Actuator 監控功能的簡介及禁用

Spring Boot Actuator: Production-ready Features 1. 添加依賴 <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency> </dependencie…

Matlab(1)

一、基本操作1. matlab四則運算規則&#xff1a;先乘除后加減&#xff0c;從左到右2、對數和指數的表示sin(pi^0.5)log(tan(1))exp&#xff08;sin&#xff08;10&#xff09;&#xff09;3、類型&#xff1a;matlab變量默認為double4、who&whos&#xff1a;命令行輸入who&…

Kotlin Android 開發腳手架封裝

Kotlin Android 開發腳手架封裝&#xff08;模塊化版本&#xff09; 我將按照模塊化設計原則&#xff0c;將腳手架拆分為多個文件&#xff0c;每個文件負責特定功能領域&#xff1a; 1. 核心初始化模塊 文件路徑: core/AppScaffold.kt object AppScaffold {lateinit var contex…

Flutter 報錯解析:No TabController for TabBar 的完整解決方案

目錄 Flutter 報錯解析&#xff1a;No TabController for TabBar 的完整解決方案 一、錯誤場景&#xff1a;當 TabBar 失去 "指揮官" 二、為什么 TabBar 必須依賴 Controller&#xff1f; 1. TabBar 與 TabController 的協作關系 2. 狀態管理的核心作用 3. 實戰…

【24】C++實戰篇——【 C++ 外部變量】 C++多個文件共用一個枚舉變量,外部變量 extern,枚舉外部變量 enum

文章目錄1 方法2 外部變量 應用2.1 普通外部全局變量2.2 枚舉外部全局變量 應用2.2.2 枚舉外部變量優化c多個文件中如何共用一個全局變量 c頭文件的使用和多個文件中如何共用一個全局變量 C共享枚舉類型給QML 1 方法 ①頭文件中 聲明外部全局變量&#xff1b; ②在頭文件對…

Linux SELinux 核心概念與管理

Linux SELinux 核心概念與管理一、SELinux 基本概念 SELinux 即安全增強型 Linux&#xff08;Security-Enhanced Linux&#xff09;&#xff0c;由美國國家安全局&#xff08;NSA&#xff09;開發&#xff0c;是一套基于強制訪問控制&#xff08;MAC&#xff09;的安全機制&…

Git 中**未暫存**和**未跟蹤**的區別:

文件狀態分類 Git 中的文件有以下幾種狀態&#xff1a; 工作區文件狀態&#xff1a; ├── 未跟蹤 (Untracked) ├── 已跟蹤 (Tracked)├── 未修改 (Unmodified) ├── 已修改未暫存 (Modified/Unstaged)└── 已暫存 (Staged)1. 未跟蹤 (Untracked) 定義&#xff1a;Gi…

前端1.0

目錄 一、 什么是前端 二、 HTML 1.0 概述 2.0 注釋 三、開發環境的搭建 1.0 插件 2.0 筆記 四、 常見標簽&#xff08;重點&#xff09; 四、案例展示&#xff08;圖片代碼&#xff09; 五、CSS引入 一、 什么是前端 web前端 用來直接給用戶呈現一個一個的網頁 …

Flutter鏡像替換

一、核心鏡像替換&#xff08;針對 Maven 倉庫&#xff09; Flutter 依賴的 Google Maven 倉庫&#xff08;https://maven.google.com 或 https://dl.google.com/dl/android/maven2&#xff09;可替換為國內鏡像&#xff0c;常見的有&#xff1a;阿里云鏡像&#xff08;推薦&am…

MATLAB實現的改進遺傳算法用于有約束優化問題

基于MATLAB實現的改進遺傳算法&#xff08;GA&#xff09;用于有約束優化問題的代碼&#xff0c;包括處理非線性約束。此代碼通過引入懲罰函數和修復機制&#xff0c;有效處理約束條件&#xff0c;提高算法的魯棒性和收斂速度。 1. 定義優化問題 % 定義目標函數 function f ob…

Qt子類化QWidget后,使用setStyleSheet設置樣式無效的解決方案

關鍵代碼&#xff1a; #include <QPainter> #include <QStyleOption>void paintEvent(QPaintEvent *e) {QStyleOption opt;opt.init(this);QPainter p(this);style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);QWidget::paintEvent(e); }定義…

【python中級】關于Flask服務在同一系統里如何只被運行一次

【python中級】關于Flask服務在同一系統里如何只被運行一次 1.背景 2.方案1 2.方案2 1.背景 python Flask實現的一個http服務,打包成應用程序exe后在windows10系統運行; 由于我會不斷的更新這個http服務,我希望運行這個http服務的時候之前的http服務被停掉; 即實現 Pytho…