说来惭愧 以前对数据库的运用一直很不熟练,刚刚好通过自制orm这个过程可以熟悉一下嵌入式数据库操作 一开始我使用的最普通的数据库连接方式,但是后发现连接效率很低,同时也缺乏相应的连接管理机制,后来开发群里的一个前辈提醒我改用连接池来管理连接,所以就有下面的代码了

在下面的代码中我应用了DBUtils数据库连接池 包模块中的PooledDB DBUtils提供两种外部接口:

  • PersistentDB :提供线程专用的数据库连接,并自动管理连接。
  • PooledDB :提供线程间可共享的数据库连接,并自动管理连接。

PersistentDB 和 PooledDB 都是为了重用数据库连接来提高性能,并保持数据库的稳定性。

所以选择何种模块,可以参考上面的解释。 PersistentDB 将会保持一定数量的连接供频繁使用。在这种情况下总是保持固定数量的连接。如果你的程序频繁的启动和关闭线程,最好使用 PooledDB

又到了贴代码的时刻啦!!!!

#encoding=utf-8
import MySQLdb
import sys
from log import logger
from DBUtils.PooledDB import PooledDB
from config import DATABASES

class Mysql(object):
    Mysql_Pool = None
    conn_num = 0
    pool_num = 0

    def __init__(self):
        Mysql.Mysql_Pool = Mysql.GetConnection()
    @staticmethod
    def GetConnection():
        if Mysql.Mysql_Pool is None:
            Mysql.pool_num+=1
            Mysql_Pool = PooledDB(creator=MySQLdb,mincached =1,maxcached =200,
                host = DATABASES["HOST"],port = DATABASES["PORT"],user = DATABASES["USER"],
                db = DATABASES["NAME"],use_unicode=False,charset=DATABASES["CHAR"])
            return Mysql_Pool
    @staticmethod
    def Get_conn():
        if Mysql.Mysql_Pool is None:
            Mysql()
            Mysql.conn_num +=1
            return Mysql.Mysql_Pool.connection()
        else:
            Mysql.conn_num +=1
            return Mysql.Mysql_Pool.connection()

在上面的代码中我实现了功能类似于单例模式的mysql连接池的封装,用户只需要调用 Mysql. Get_conn()就可以获取一个连接 使用连接池后我们只管使用连接就好了,不用担心其他的问题,而且效率比普通的连接大致快了6倍左右.

下面来看看basemodel的类,在定义模型的时候理论上最好继承中国基类,这样就是可以愉快调用写好在basemodel里面的各种方法了,同样这类会比较大,毕竟有那么多的方法可以自定义,下面就简单的把关键的代码贴出来看一看解释解释一下:

class BaseModel(object):
    """docstring for BaseModel :这是一个model的基类,建议所有的model都继承这个类
    这样就可以正大光明的使用里面
    自己定义的各种sql语句的封装了"""
    def __init__(self,name,args={}):
        print 'init BaseModel',name
        self.table = name
        result = None
        self.index =None
        print self.table
        self.mysql_conn = Mysql.Get_conn()
        self.cur = self.mysql_conn.cursor()
        if len(args)>0:
            sql= self.prepare_sql('select',args)
            try:
                self.cur.execute(sql)
                result= self.cur.fetchone()

            except MySQLdb.Error,e:
                print "Mysql Error %d: %s" % (e.args[0], e.args[1])
            if result!=None:
                self.index= result[0]
                print 'self.index = ',self.index
    def __del__(self):
        print 'eciting'
        self.cur.close()
        self.mysql_conn.commit()
        self.mysql_conn.close()

    def prepare_sql(self,method,args={}):
        avalible_method = ['insert','select','update','delete']
        exe_method = None
        if method in avalible_method:
            exe_method = method
        else:
            return "there is invalide method ,avalible_method in ['insert','select','update','delete']"

        if exe_method =="select":
            sql_str ="select * from "+self.table+" where "

            if len(args)>0:
                for key in args:
                    if isinstance(args[key],str):
                        sql_str+= str(key)+ " = '" +str(args[key])+"' and "
                    else:
                        sql_str+= str(key)+ " = " +str(args[key])+" and "

            return sql_str.strip(" and ")

        elif exe_method == "insert":
            key= " ("

            key += "".join([i+"," for i in args]).strip(",")
            print key
            value=""
            for i in args:
                if isinstance(args[i],str):
                    value+="'"+args[i]+"',"
                else:
                    value+= str(args[i])+","
            print value
            sql_str = "insert into "+self.table+key+") values("+value.strip(",")+")"
            return sql_str


        elif exe_method =="update":
            strings=""
            for i in args:
                if isinstance(args[i],str):

                    strings += " "+i+"='"+args[i]+"',"
                else:
                    strings += " "+i+"="+str(args[i])+","
            if self.index==None:
                raise DatabaseError("please instance the BaseModel")
            sql_str = "update "+self.table+" set "+strings.strip(",")+" where id="+ str(self.index)
            return sql_str


        elif exe_method=="delete":
            if self.index ==None:
                raise DatabaseError("please instance the BaseModel")
            sql_str = "delete from "+self.table+" where id = "+str(self.index)
            return sql_str
    def find(self,**args):

        sql= self.prepare_sql('select',args)
        print sql
        result = None
        try:
            self.cur.execute(sql)
            result= self.cur.fetchall()
        except MySQLdb.Error,e:
            print "Mysql Error %d: %s" % (e.args[0], e.args[1])
        #print isinstance(result[1][2],unicode)
        print result 
        return result

下面来简单的解释一下里面的几个核心的函数的作用

  1. init()函数主要是用来初始化basemodel,同时向mysql类连接池申请一个连接,同时初始化一个游标,
  2. del()的方法主要是在调用类结束后自动把连接关闭,把资源空出来还给连接池.
  3. prepare_sql()主要功能是拼接sql原生语句,然后返回这个sql语句,
  4. find()这个函数就是具体的orm功能函数了,用户可调用这个方法来找到匹配的数据行.同时还有其他的get,insert,update.delete等常用的方法,就不一一解释了,当然也可以直接调用mysql类来申请一个连接,直接调用cur.execute()来直接使用原生的sql语句.

在使用的时候大致可以像下面的代码示例那样子使用,当然还有更多很灵活的用法,iotshine的orm并没有做太多的工作,只是做了点简单的封装.

class device_sensor(BaseModel):
def __init__(self,**args):
    super(device_sensor, self).__init__(self.__class__.__name__,args)
    print self.table
if __name__ == "__main__":
    #a = device_sensor().find(sensor_name="Int 传感器")
    #b = device_sensor().find(data_type=1)

    #c = device_sensor().insert(sensor_name='outshine',sensor_slug=234,is_active=1,sensor_device_id=1,data_type=1)
    #x.update(data_type=1,sensor_slug=233)
    #b.update(data_type=1,sensor_slug=233)

目前在orm是简单的不能再简单的,后面会参考先进的orm进行修改个改进,争取在好用和轻量之中做到平衡

下一篇要讲讲关于异步任务队列,异步任务队列对于我们的平台的性能是很关键的一步,如果没有异步队列,我们前面的epoll模型也是没有什么用的,毕竟数据库连接是涉及到io阻塞的,这个会极大的阻塞整个线程. 下一篇也是我在2015年最后一篇, 后面的开发和完善要等考试月结束后寒假回家安安静静的开发了



Copyright © 2019 outshineamaze.
All rights reserved.

results matching ""

    No results matching ""