zoukankan      html  css  js  c++  java
  • Day4

    今日总结:

    1.数据库学习总结

      因为这部分的内容都是记在纸上,一共四页。所以博客里的内容比较少

    2.重写ORM框架:

      之前在使用aiomysql+sqlalchemy的学习中,因为不太熟悉ORM的操作,结果将数据库连接和ORM写在了一起,这样造成了较强的耦合,不利于SQL的扩展;

    而今天的学习呢,思路更加明确了。使用aiomysql来执行SQL语句、连接、返回数据结果;SQLalchemy呢,它主要用来进行数据库关系映射ORM,以及生成SQL语句。

    这样一来,思路清晰了很多;虽然aiomysql能代替一些SQLalchemy的功能,或者SQLalchemy能直接执行数据库的执行操作(使用sessionmaker),但是这样混乱的使用,

    显然对程序的开发是不友好的,方便,但是降低了开发的效率;

    今日学习:

      -重写ORM框架,我会从这三个方面叙述:1.实现了哪些功能 2.为什么要这样实现 3.我遇到了哪些问题

      1.将数据库连接单独写成一层,Class DBcontroller类,初始化连接时,会使用单例模式(创建一个pool),用户不使用相同的conn,但却在同一个pool下,解决了用户使用单一连线造成的问题(服务器压力,数据传输之类的);同时用户也不用需要手动去连接mysql服务器。 

      

     1 class DBcontroller:
     2     __engine=None
     3     __isinstance = False
     4     def __new__(cls, *args, **kwargs):
     5         if cls.__isinstance:  # 如果被实例化了
     6             return cls.__isinstance  # 返回实例化对象
     7         print('connecting to database...')
     8         asyncio.get_event_loop().run_until_complete(DBcontroller.connect())
     9         cls.__isinstance = object.__new__(cls)  # 否则实例化
    10         return cls.__isinstance  # 返回实例化的对象
    11 
    12     @staticmethod
    13     async def connect():
    14         try:
    15             __engine = await create_engine(user='root',
    16                                               db='youku',
    17                                               host='127.0.0.1',
    18                                               password='root',
    19                                               minsize=1,
    20                                               maxsize=10,
    21                                               autocommit=True)
    22             if __engine:
    23                 DBcontroller.__engine = __engine
    24                 DBcontroller.connectStatue =True
    25                 print('connect to mysql success!')
    26             else:
    27                 raise ("connect to mysql error ")
    28         except:
    29             print('connect error.', exc_info=True)
    30 
    31     def selectTable(self,sql):
    32         res=''
    33         async def select(res):
    34             conn = await DBcontroller.__engine.acquire()
    35             try:
    36                 result = await conn.execute(sql)
    37                 res = await result.fetchall()
    38                 # for row in res:
    39                 #     print(row)
    40             except Exception as e :
    41                 print(e)
    42             finally:
    43                 DBcontroller.__engine.release(conn)
    44                 return res
    45         res = asyncio.get_event_loop().run_until_complete(select(res))
    46         return res
    47 
    48     def executeTable(self,sql):
    49         res=''
    50         async def execute(res,sql):
    51             conn = await DBcontroller.__engine.acquire()
    52             try:
    53                 result = await conn.execute(sql)
    54                 res = result.lastrowid
    55                 print('操作执行完毕')
    56             except Exception as e:
    57                 if e.args[0]== 1062:
    58                     print('主键已存在')
    59                 else:
    60                     print(f'插入失败:{e}')
    61             finally:
    62                 DBcontroller.__engine.release(conn)
    63                 return res
    64         lastrowid = asyncio.get_event_loop().run_until_complete(execute(res,sql))
    65         return lastrowid
    DBcontroller

      2.自动生成Model.py,但前提必须使用sqlalchemy,在CMD里使用这串代码,就可以自动生成Model.py,解放了时间:

    sqlacodegen mysql+pymysql://root:root@127.0.0.1:3306/automovie > models.py

        自动生成的Model里的类,也带有__table__,__mapper___等和sqlalchemy相同属性的类

      

      3.使用sqlalchemy生成sql语句,例如User类,ygy=User(name='杨归元',age=18),

    使用sqlchemy.select('*').select_from(User.__table__).where(User.__table__.c.age==ygy.age),

    那么可以生成"SELECT * FROM USER WHERE USER.AGE = 18"的句子;这里也就是为什么要使用ORM的原因吧!

    1.为了防止SQL注入,用户不可能通过输入属性值来造成sql注入,因为中间有一层ORM;SQL没有直接裸露出来

    2.为了是开发者,能够更加专注的去写业务逻辑层,不用去担心SQL语句到底要去怎么写;(当然直接写SQL也是种另外的感受)

      

      4.类似的语句还有这样的:self.__table__.update().values(attr).where(where)

    具体网址在这里:https://www.osgeo.cn/sqlalchemy/core/dml.html

      

       5.为了获取user的属性,我去找了父类sqlalchemy.ext.declarative.declarative_base,去这里面的函数一个一个去看,然后又去百度了各种官方文档,

    最后无解,时间都浪费在了这里,最后的解决方法是这样的,

      使用user.__dict__,获取属性;

      如果遇到inser操作时,插入成功了,那么我们要把user剩下的属性给返回,比如user.datatime,user.id;这些都是需要更新的;

      所以这个时候select一次user,然后将获得的属性值赋值给user.__dict__,结局失败了,原因不知;

      最后的解决方法是这样的:select返回一个对象,从数据库里取出属性,然后根据这个属性列表新建一个相应的对象

      6.如何使select方法返回一个对象?

       conn.execute(sql)之后,会返回一个resultProxy对象,

      可以for key, value in result.items()来获取列名和列表值:

        key:id value:1

        ...

        key:age value:18

      同时通过,type(self)获取它的类名

        那么 newuser = type(self)(),就可以新建了一个相同的对象

      7.当执行 result = await conn.execute(insertSQL)后,result.fetchall()会报异常,但是对系统运行没有影响:

      这里有关mysql的一个叫Nocount的东西:

      Set Nocount on

      当SET NOCOUNT on时候,将不向客户端发送存储过程每个语句的DONE_IN_proc消息,如果存储过程中包含一些并不返回实际数据的语句,网络通信流量便会大量减少,可以显著提高应用程序性能;

      插入执行结束后,没有返回值,但是我们却获取了返回值;但我们可以获取result.lastrowid,把刚插入的数据的id拿到

      8.以后再也不想研究ORM了。。。

      但是通过这几天的学习,我感觉自己的收获很多,从数据库引擎到数据库,从数据库到ORM,各方各面,条条划划的地方都有学习到,也算是不错的收获

  • 相关阅读:
    loadrunder之脚本篇——集合点设置
    Loadrunner之脚本篇——事务函数
    Loadrunder之脚本篇——事务时间简介
    Loadrunder之脚本篇——参数化在场景中的运用
    Java提高(一)---- HashMap
    阅读收集
    SpringMVC是什么?
    elasticsearch head安装
    Elasticsearch 全量遍历数据
    JVM 堆内存,参数优化
  • 原文地址:https://www.cnblogs.com/ygy1997/p/11795237.html
Copyright © 2011-2022 走看看