平滑访问由抽象Sql语句构造的数据
类型:电子教程大小:8.5M语言:中文评分:8.3标签:立即下载。如果使用数据库作为持久化设备,是直接写sql还是使用ORM?毫无疑问,ORM的出现给了我们一个全新的数据操作视角:在面向对象语言中,用面向对象的方法访问和操作数据,但是使用一段时间后,总会觉得有点别扭,因为关系数据库中数据的抽象方式是基于关系代数的层次结构,而面向对象数据的抽象方式是网络结构, 而这两种抽象模式之间的ORM映射会产生阻抗不匹配的现象,所以在映射的时候,那么我再想一想,如果抽象数据本身就存在阻抗不匹配的问题,那如果我们抽象对数据的访问呢? 无论如何,对关系数据库的访问仍然是通过SQL语句作为访问接口,那么如果抽象SQL语句,能否摆脱阻抗不平衡,顺利访问操作数据呢?我在上一篇文章中发布的Python DAL中做了一个小小的尝试。当然,我不是第一个这样做的人,但我想总结一下这个方法,它可能会在ORM之外提供一个更新的视角,并产生一个更轻量级的数据访问组件,这也是好的。我用Python来实现,因为暂时只想用动态语言来实现。如果我需要在下面使用。NET,我可以使用IronPython。如果有同学想到如何在C#下实现,也希望与大家分享。为什么要用动态语言?首先,您不需要实体类,因为我们抽象了访问数据的方式,而不是数据本身。在关系数据库中,数据是以数据行和字段的形式存在的。在数据结构上,一行数据可以用字典来表示。在python中,我们可以用以下形式表示字典:class row(dict): def _ _ getattr _ _(self,property name) : if self。has _ key(属性名):返回self[属性名]返回none
这样,我们可以通过列出相应的属性来访问Row对象的键值,就像实体类一样,从而解决了数据抽象的问题。接下来,我们要抽象出SQL。首先,我们需要分析SQL的结构。我们有四种类型的数据操作:添加、删除、更改和查询,它们由四个SQL语句实现:插入、删除、更新和选择。每个SQL语句都由子句组成。四条SQL语句的子句都有自己独特的子句和常见的子句,例如WHERE子句。SELECT、UPDATE、DELETE都有相同语义的WHERE子句,都表示要操作的数据被过滤到条件中,所以我抽象过滤条件,定义conds类。类条件:def __init__(自身,字段):自身。field _ name=fieldself。_ SQL=' '自我。_ params=[] self。_ has _ value=假自我。_ sub _ conds=[] self。_ no _ value=false该类用于将语言的关系操作逻辑映射到SQL语句。幸运的是,Python支持运算符重载示例:def _ _ eq _ _ (self,value) :返回self。_准备(')。join ([' `,self。field _ name,' `=% s']),值)
def _prepare(self,sql,value):如果不是self。_has_value:self。_sql=sqlself。_params.append(value)self。_has_value=Truereturn自升操作错误,“多种操作条件”
上面的代码定义了如果conds('col1')==5,它将映射到sql col1=%s,并添加一个值为5的参数。同样,其他关系运算符的方法也映射到相应的内置方法。这两种关系是和和或。我们使用__和__和_ _或_ _来映射它们。如果like找不到对应的运算符,则使用Like方法来表示这种关系。条件运算的结果仍然是一个条件,所以应该使用对象本身作为返回值。这样,(conds(' col 1 ')==5)(conds(' col 2 ')6)映射到条件col1=%s和col2%s% s的并集,由于用字符串表示列名不方便,我们定义了一个表类来获得conds: class tablequery: ' ' '对单表简单查询的支持' ' def _ _ init _ _ (self,db,tablename) :self。tablename=tablenameelf。db=db
def __call__(self,query=None): return operator(self . db,self.tablename,query)
def __getattr__(self,field _ name): return conds(field _ name)
同样的,我们添加getattr,def _ _ getattr _ _ (self,tablename) : '''为select table返回单个表查询程序' ' '返回表查询程序(self,tablename)然后我们可以通过db.tablename.colname得到条件对象前面的例子可以改为(db . Tablename . col 1==5)(db . Tablename . col 26),如果预置了tb=db.tablename,可以改写为(tb.col1==t)(tb.col26)。
因为插入数据只需要数据表名,不需要基于查询,所以insert方法直接添加到TableQueryer中,所以插入数据只需要db . tablename . insert(col 1=value 1,col2=value2.)
数据的查询、更新、删除都是基于查询条件的,所以抽象出一个名为“oper”的操作对象:类运算符3360def _ _ init _ _ (self,db,tablename,query) :self。计数=计数(数据库、表名、查询)自身。选择=选择(数据库、表名、查询)自身。更新=更新(数据库、表名、查询)自身。删除=删除(数据库、表名、查询)
每个操作抽象一个类,查询条件保存在每个操作的条件中。最终的Sql生成和特定子句的添加在特定的类中完成,例如Select。在这里,为了保存一个方法名的层次结构,我把TableQueryer做成了一个可以调用的对象,并添加了__call__方法。将查询条件传递给__call__方法会返回一个Operator对象,因此可以通过TB=db . tablename q=TB((TB . col 1==5)(TB . col 26))q . select()来查询结果。等效的sql是select * from tablename,其中col1=5,col26。获取q后,可以通过直接调用q.delete()删除这些数据。q.update(tb.col1==6)可以更新过滤后的数据,q.delete()可以直接删除符合过滤条件的数据
该项目位于http://bitbucket.org/Alexander李/流畅-SQL-数据访问层
版权声明:平滑访问由抽象Sql语句构造的数据是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。