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
方法就行,由于每次实例化的对象不一样所以就不会有数据覆盖了;