twisted實現MMORPG 游戲數據庫操作封裝設計與實現

在設計 MMORPG(大規模多人在線角色扮演游戲)時,數據庫系統是游戲架構中至關重要的一部分。數據庫不僅承擔了游戲中各種數據(如玩家數據、物品數據、游戲世界狀態等)的存儲和管理任務,還必須高效地支持并發訪問、事務處理和復雜的查詢。為了確保系統的可擴展性和維護性,我們需要對數據庫操作進行封裝和模塊化設計。

為了實現上述目標,本文設計了一個基于 Twisted 的數據庫封裝系統。Twisted 是一個異步框架,適用于處理大量并發任務。結合 Twisted 和數據庫連接池(adbapi.ConnectionPool),我們可以高效地執行異步數據庫操作。
在這里插入圖片描述

在這里插入圖片描述

1. DatabaseError
作用:自定義異常類,用于在數據庫操作發生錯誤時拋出詳細的錯誤信息,包含錯誤消息和錯誤碼(默認為500)。2. DatabaseOperation
作用:抽象基類,定義了數據庫操作的統一接口。所有具體的數據庫操作類(如 SelectOperation, InsertOperation 等)都繼承自此類,必須實現 excute 方法來執行數據庫事務。
關鍵方法:
executeQuery:執行實際的 SQL 查詢。
handleSuccess:操作成功時的回調函數。
handleFailure:操作失敗時的回調函數。3. SelectOperation
作用:繼承自 DatabaseOperation,封裝了 SELECT 查詢操作。提供了 executeQuery 方法來執行 SQL 查詢,并返回查詢結果。
關鍵方法:
executeQuery:執行 SELECT 查詢,并根據提供的表名、列名、查詢條件等生成 SQL 語句。
excute:實現 DatabaseOperation 中的抽象方法,執行查詢操作。4. InsertOperation
作用:繼承自 DatabaseOperation,封裝了 INSERT 插入操作。通過 executeQuery 方法生成插入的 SQL 語句并執行。
關鍵方法:
executeQuery:構建并執行 INSERT SQL 語句,將數據插入指定的表。
excute:實現 DatabaseOperation 中的抽象方法,執行插入操作。5. UpdateOperation
作用:繼承自 DatabaseOperation,封裝了 UPDATE 更新操作。通過 executeQuery 方法生成更新的 SQL 語句并執行。
關鍵方法:
executeQuery:構建并執行 UPDATE SQL 語句,用新值更新指定的行。
excute:實現 DatabaseOperation 中的抽象方法,執行更新操作。6. DeleteOperation
作用:繼承自 DatabaseOperation,封裝了 DELETE 刪除操作。通過 executeQuery 方法生成刪除的 SQL 語句并執行。
關鍵方法:
executeQuery:構建并執行 DELETE SQL 語句,根據指定條件刪除記錄。
excute:實現 DatabaseOperation 中的抽象方法,執行刪除操作。
7. DatabaseManager
作用:負責數據庫連接池的管理和數據庫操作的執行。它使用 adbapi.ConnectionPool 創建數據庫連接池,執行操作并處理事務。
關鍵方法:
getConnection:返回數據庫連接池的實例。
executeOperation:接受一個數據庫操作對象,調用 runInteraction 方法來執行異步數據庫事務,并處理操作成功或失敗的回調。
8. GameQueryPlayerId
作用:繼承自 SelectOperation,封裝了查詢玩家信息的操作。它指定查詢條件為玩家的名稱,并通過 excute 方法執行查詢。
關鍵方法:
excute:執行 SelectOperation 中的 executeQuery 方法,查詢玩家 ID。
set_query_name:設置查詢的玩家名稱。

代碼

from twisted.enterprise import adbapi
from twisted.internet.defer import Deferred
import pymysql
import traceback
from twisted.internet import reactor
from functools import partial
from abc import ABC, abstractmethod
# 異常類定義
class DatabaseError(Exception):def __init__(self, message, code=500):self.message = messageself.code = code# 抽象的數據庫操作類
class IDatabaseOperation(ABC):@abstractmethoddef executeQuery(self, txn, table: str, columns: list, values: dict = {}, condition: dict = None) -> any:passdef handleSuccess(self, result: any):print("Operation succeeded with result:", result)def handleFailure(self, error: Exception):# 這里做一些額外的錯誤處理,比如記錄日志或者返回友好的錯誤信息print("Operation failed:", error)@abstractmethoddef excute(self, txn):#這里封裝代碼passclass ABC_SelectOperation(IDatabaseOperation):def executeQuery(self, txn, table: str, columns: list = None, values: dict = None, condition: dict = None) -> any:try:column_str = ", ".join(columns) if columns else "*"query = f"SELECT {column_str} FROM {table}"if condition:condition_str = " AND ".join([f"{key} = %s" for key in condition.keys()])query += f" WHERE {condition_str}"print(f"Executing query: {query}, with values: {tuple(condition.values()) if condition else ()}")txn.execute(query, tuple(condition.values()) if condition else ())  # use condition values if anyresult = txn.fetchall()return resultexcept Exception as e:print(f"Error executing query: {e}")traceback.print_exc()# 返回一個失敗的結果以便繼續后續操作return {"error": str(e)}@abstractmethoddef excute(self, txn):passclass ABC_InsertOperation(IDatabaseOperation):def executeQuery(self, txn, table: str, columns: list = None, values: dict = None, condition: dict = None) -> any:try:column_str = ", ".join(columns)placeholders = ", ".join(["%s"] * len(columns))  # Create placeholders based on column length# Extract values from the dictionary for each columnvalue_tuple = tuple(values[col] for col in columns)query = f"INSERT INTO {table} ({column_str}) VALUES ({placeholders})"print(f"Executing insert query: {query}, with values: {value_tuple}")txn.execute(query, value_tuple)  # Use parameterized queryreturn txn.lastrowid  # Return the inserted record IDexcept Exception as e:print(f"Error executing insert query: {e}")traceback.print_exc()# 返回一個失敗的結果以便繼續后續操作return {"error": str(e)}@abstractmethoddef excute(self, txn):passclass ABC_UpdateOperation(IDatabaseOperation):def executeQuery(self, txn, table: str, columns: list = None, values: dict = None, condition: dict = None) -> any:try:if condition and not isinstance(condition, dict):raise TypeError("Condition must be a dictionary")set_str = ", ".join([f"{col} = %s" for col in columns])query = f"UPDATE {table} SET {set_str}"# Ensure that values is passed as a tuple for updatevalue_tuple = tuple(values[col] for col in columns)if condition:condition_str = " AND ".join([f"{key} = %s" for key in condition.keys()])query += f" WHERE {condition_str}"value_tuple += tuple(condition.values())  # Append condition valuesprint(f"Executing update query: {query}, with values: {value_tuple}")txn.execute(query, value_tuple)  # Use parameterized querytxn.connection.commit()return txn.rowcount  # Return the number of updated rowsexcept Exception as e:print(f"Error executing update query: {e}")traceback.print_exc()# 返回一個失敗的結果以便繼續后續操作return {"error": str(e)}@abstractmethoddef excute(self, txn):passclass ABC_DeleteOperation(IDatabaseOperation):def executeQuery(self, txn, table: str, columns: list = None, values: dict = None, condition: dict = None) -> any:try:if not condition:raise ValueError("Condition for deletion cannot be empty.")condition_str = " AND ".join([f"{key} = %s" for key in condition.keys()])query = f"DELETE FROM {table} WHERE {condition_str}"print(f"Executing delete query: {query}, with values: {tuple(condition.values())}")txn.execute(query, tuple(condition.values()))  # Use condition values for parameterized queryreturn txn.rowcountexcept Exception as e:print(f"Error executing delete query: {e}")traceback.print_exc()# 返回一個失敗的結果以便繼續后續操作return {"error": str(e)}@abstractmethoddef excute(self):pass# 數據庫管理類,負責數據庫連接池和事務
class DatabaseManager:def __init__(self, db_config):# 初始化數據庫連接池self.dbConnectionPool = adbapi.ConnectionPool("pymysql", **db_config)def getConnection(self):return self.dbConnectionPooldef executeOperation(self, operation: DatabaseOperation) -> Deferred:try:# 使用 partial 創建一個指定了參數的函數deferred = self.dbConnectionPool.runInteraction(operation.excute)deferred.addCallback(operation.handleSuccess)deferred.addErrback(operation.handleFailure)return deferredexcept Exception as e:error = DatabaseError(str(e), 500)operation.handleFailure(error)return None# 示例數據庫配置
db_config = {'host': 'localhost','user': 'root','password': 'root','database': 'test',
}class GameQueryPlayerId(ABC_SelectOperation):def __init__(self):self.select_columns = ["name", "id"]self.elect_condition = {"name": "new_name"}  # 在此給出查詢條件def excute(self, txn):# 執行查詢操作return self.executeQuery(txn,"test", columns=self.select_columns, condition=self.elect_condition )def set_query_name(self, name):self.elect_condition["name"] = name# 示例操作
def main():# 創建DatabaseManager實例db_manager = DatabaseManager(db_config)ccGameQueryPlayerId = GameQueryPlayerId()ccGameQueryPlayerId.set_query_name("new_name")deferred = db_manager.executeOperation(ccGameQueryPlayerId)reactor.run()if __name__ == "__main__":main()

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

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

相關文章

【R語言】聚類分析

聚類分析是一種常用的無監督學習方法,是將所觀測的事物或者指標進行分類的一種統計分析方法,其目的是通過辨認在某些特征上相似的事物,并將它們分成各種類別。R語言提供了多種聚類分析的方法和包。 方法優點缺點適用場景K-means計算效率高需…

超全Deepseek資料包,deepseek下載安裝部署提示詞及本地部署指南介紹

該資料包涵蓋了DeepSeek模型的下載、安裝、部署以及本地運行的詳細指南,適合希望在本地環境中高效運行DeepSeek模型的用戶。資料包不僅包括基礎的安裝步驟,還提供了68G多套獨立部署視頻教程教程,針對不同硬件配置的模型選擇建議,以…

Java Spring boot 篇:常用注解

Configuration 作用 Configuration 注解的核心作用是把一個類標記為 Spring 應用上下文里的配置類。配置類就像一個 Java 版的 XML 配置文件,能夠在其中定義 Bean 定義和 Bean 之間的依賴關系。當 Spring 容器啟動時,會掃描這些配置類,解析其…

在 Ubuntu 20.04 為 Clash Verge AppImage 創建桌面圖標教程

在 Ubuntu 20.04 為 AppImage 創建桌面圖標教程 一、準備工作 確保你已經下載了 xxxx.AppImage 文件,并且知道它所在的具體路徑。同時,你可以準備一個合適的圖標文件(.png 格式)用于代表該應用程序,如果沒有合適的圖…

【復現DeepSeek-R1之Open R1實戰】系列6:GRPO源碼逐行深度解析(上)

目錄 4 GRPO源碼分析4.1 數據類 GRPOScriptArguments4.2 系統提示字符串 SYSTEM_PROMPT4.3 獎勵函數4.3.1 accuracy_reward函數4.3.2 verify函數4.3.3 format_reward函數 4.4 將數據集格式化為對話形式4.5 初始化GRPO Trainer 【復現DeepSeek-R1之Open R1實戰】系列3&#xff1…

【雜談】加油!!!!

為了在三月底前系統準備Java后端開發的面試和筆試,以下是分階段的高效學習計劃: 一、知識體系構建(第1-2周) 核心基礎強化 Java基礎(每日1.5小時): 重點掌握:JVM內存模型&#xff0…

python旅游推薦系統+爬蟲+可視化(協同過濾算法)

??基于用戶的協同過濾算法 ??有后臺管理 ??2w多數據集 這個旅游數據分析推薦系統采用了Python語言、Django框架、MySQL數據庫、requests庫進行網絡爬蟲開發、機器學習中的協同過濾算法、ECharts數據可視化技術,以實現從網站抓取旅游數據、個性化推薦和直觀展…

HarmonyNext上傳用戶相冊圖片到服務器

圖片選擇就不用說了,直接用 無須申請權限 。 上傳圖片,步驟和android對比稍微有點復雜,可能是為了安全性考慮,需要將圖片先拷貝到緩存目錄下面,然后再上傳,當然你也可以轉成Base64,然后和服務…

同為科技智能PDU助力Deepseek人工智能和數據交互的快速發展

1 2025開年,人工智能領域迎來了一場前所未有的變革。Deepseek成為代表“東方力量”的開年王炸,不僅在國內掀起了技術熱潮,并且在全球范圍內引起了高度關注。Deepseek以顛覆性技術突破和現象級應用場景席卷全球,這不僅重塑了產業格…

二、QEMU NFS 環境搭建

? 在上一章節中,我們已經成功完成了內核和 busybox 環境的配置。為了進一步提高開發效率,我們可以使用 NFS(Network File System)來掛載根目錄。NFS 允許我們將本地文件系統通過網絡共享給虛擬機使用,這樣在開發過程中…

.NET 9.0 的 Blazor Web App 項目中 EF Core 【事務】使用備忘

一、DbContext.Database.BeginTransactionAsync() 模式 1. 注意事項:連接字符串中啟用了 MARS(Multiple Active Result Sets:MultipleActiveResultSetsTrue )后,無法創建 保存點(保存點與 SQL Server 的多…

記一次 Git Fetch 后切換分支為空的情況

Git Fetch 后切換分支為空的情況 在使用 Git 時,我遇到這樣的情況:執行 git fetch 后切換分支,發現工作目錄是空的,沒有任何文件,所以插眼記錄一下。 原因分析 git fetch 的作用:git fetch 只會從遠程倉庫…

UMLS數據下載及訪問

UMLS數據申請 這個直接在官網上申請即可,記得把地址填全,基本都會拿到lisence。 UMLS數據訪問 UMLS的數據訪問分為網頁訪問,API訪問以及數據下載后的本地訪問,網頁訪問,API訪問按照官網的指示即可,這里主…

使用 Docker 部署 Apache Spark 集群教程

簡介 Apache Spark 是一個強大的統一分析引擎,用于大規模數據處理。本文將詳細介紹如何使用 Docker 和 Docker Compose 快速部署一個包含一個 Master 節點和兩個 Worker 節點的 Spark 集群。這種方法不僅簡化了集群的搭建過程,還提供了資源隔離、易于擴…

瑞薩RA-T系列芯片ADCGPT功能模塊的配合使用

在馬達或電源工程中,往往需要采集多路AD信號,且這些信號的優先級和采樣時機不相同。本篇介紹在使用RA-T系列芯片建立馬達或電源工程時,如何根據需求來設置主要功能模塊ADC&GPT,包括采樣通道打包和分組,GPT觸發啟動…

20250217 隨筆 redis非原子性操作簡述

從你提供的文本來看,核心是 Redis 作為緩存的檢查機制,以及非原子性操作導致的不一致性問題。 我們可以拆解為兩個部分來理解: 📌 1. 邏輯:先查 Redis,再決定是否注冊 邏輯流程 先查詢 Redis 是否有某個 …

git-提交時間和作者時間的區別

1.介紹 定義介紹 提交時間(Committer Date):決定了提交在 Git 歷史中的位置,通常影響 GitHub 上提交顯示的順序。 作者時間(Author Date):雖然不影響提交的排序,但在每個提交詳情頁…

PHP框架入門指南:從零構建現代Web應用

一、為什么需要PHP框架? 1.1 傳統PHP開發的痛點 重復造輪子:用戶認證、表單驗證等基礎功能需要反復開發代碼混亂:缺乏統一結構導致維護困難安全漏洞:手動處理SQL注入/XSS攻擊效率低下擴展性差:耦合代碼難以適應業務增長1.2 框架的核心價值 標準化架構:MVC模式強制代碼分…

Leetcode 146 LRU緩存 的三種解法

146. LRU 緩存 請你設計并實現一個滿足 LRU (最近最少使用) 緩存 約束的數據結構。 實現 LRUCache 類: LRUCache(int capacity) 以 正整數 作為容量 capacity 初始化 LRU 緩存int get(int key) 如果關鍵字 key 存在于緩存中,則返回關鍵字的值&#xff0…

尚硅谷 java 學習Day19 抽象類與抽象方法、接口、內部類

6-5 抽象類(abstract)與抽象方法(important) 一、什么叫抽象類: 有時候將一個父類設計的非常抽象,以至于它沒有具體的實例,這樣的類稱為抽象類 abstract關鍵字的使用: ? 1、abstract:抽象的 ? 2、abs…