SQLHelper ------ python實現
1.第一種:
import pymysql
import threading
from DBUtils.PooledDB import PooledDB
class SqlHelper(object):
def __init__(self):
self.pool = PooledDB(
creator=pymysql, # 使用鏈接數據庫的模塊
maxconnections=6, # 連接池允許的最大連接數,0和None表示不限制連接數
mincached=2, # 初始化時,鏈接池中至少創建的鏈接,0表示不創建
blocking=True, # 連接池中如果沒有可用連接后,是否阻塞等待。True,等待;False,不等待然后報錯
ping=0,
# ping MySQL服務端,檢查是否服務可用。# 如:0 = None = never, 1 = default = whenever it is requested, 2 = when a cursor is created, 4 = when a query is executed, 7 = always
host='127.0.0.1',
port=3306,
user='root',
password='000000',
database='flask_day1',
charset='utf8'
)
# 用來獲取local對象
self.local = threading.local()
def open(self):
"""
獲取數據庫連接,游標對象
"""
conn = self.pool.connection()
cursor = conn.cursor()
return conn,cursor
def close(self,cursor,conn):
"""
關閉游標,數據庫連接
"""
cursor.close()
conn.close()
def __enter__(self):
"""
with語句自動觸發,執行此方法
"""
conn,cursor = self.open()
rv = getattr(self.local,"stack",None)
if not rv:
self.local.stack = [(conn,cursor)]
else:
rv.append([(conn,cursor)])
self.local.stack = rv
return cursor
def __exit__(self, exc_type, exc_val, exc_tb):
"""
with語句結束時執行此方法
"""
rv = getattr(self.local,"stack",None)
if not rv:
return
conn,cursor = rv[-1]
self.close(cursor,conn)
db = SqlHelper()
# 調用文件
import threading
def task(i):
sql = "select * from book;"
with db as cur:
cur.execute(sql)
data = cur.fetchall()
print(i,data)
for i in range(5):
t = threading.Thread(target=task,args=(i,))
t.start()
說明:
這個是借鑒了多線程中的threading.local()
方法,當每個線程都會去獲取自己對應的數據,所以在每一個線程開啟時就會執行task
方法,這個方法中有with
這方法,這個方法是去調用上下文管理器,就需要執行這個對象中的__enter__()
方法和__exit__()
方法;進來時執行__enter__()
這個方法,並且需要又返回值,這個返回值就是with db as cur:
中的cur
的值,在結束的時候需要執行__exit__()
方法;在執行__enter__()
方法的時候在里邊將當前這個線程的數據寫成一個字典,字典的鍵是固定的名字stack
,字典的值是一個列表套元組形式,元組中是conn,cursor
(數據庫連接,游標對象);將這個保存到threading.local()
實例化出來的對象中self.local
,在對數據庫操作完之后,with也要執行__exit__()
方法,在這個方法中會使用現在的self.local
對象去獲取存在這個對象中的那個字典,獲取對應的值,然后對對游標進行關閉,數據的連接進行關閉;
2.第二種:
import pymysql
import threading
from DBUtils.PooledDB import PooledDB
import greenlet
POOL = PooledDB(
creator=pymysql, # 使用鏈接數據庫的模塊
maxconnections=6, # 連接池允許的最大連接數,0和None表示不限制連接數
mincached=2, # 初始化時,鏈接池中至少創建的鏈接,0表示不創建
blocking=True, # 連接池中如果沒有可用連接后,是否阻塞等待。True,等待;False,不等待然后報錯
ping=0,
# ping MySQL服務端,檢查是否服務可用。# 如:0 = None = never, 1 = default = whenever it is requested, 2 = when a cursor is created, 4 = when a query is executed, 7 = always
host='127.0.0.1',
port=3306,
user='root',
password='000000',
database='flask_day1',
charset='utf8'
)
class SqlHelper(object):
def __init__(self):
self.conn = None
self.cursor = None
def open(self):
conn = POOL.connection()
cursor = conn.cursor()
return conn,cursor
def close(self,cursor,conn):
cursor.close()
conn.close()
def __enter__(self):
self.conn,self.cursor = self.open()
return self.cursor
def __exit__(self, exc_type, exc_val, exc_tb):
self.close(self.cursor,self.conn)
調用語句:
import threading
def task(i):
sql = "select * from book;"
with SqlHelper() as cur:
cur.execute(sql)
data = cur.fetchall()
print(i,data)
for i in range(5):
t = threading.Thread(target=task,args=(i,))
t.start()
說明:
此方法比較簡單,理解起來也比較容易,首先創建一次數據庫連接池,在SqlHelper
類中只是調用執行就行,不用在重復實例化對象;每次執行sql語句是實例化SqlHelper
方法就行,由於每次實例化的對象不一樣所以就不會有數據覆蓋了;