西西軟件園多重安全檢測下載網(wǎng)站、值得信賴的軟件下載站!
軟件
軟件
文章
搜索

首頁西西教程數(shù)據(jù)庫教程 → 通過抽象Sql語句來構(gòu)建的數(shù)據(jù)流暢訪問

通過抽象Sql語句來構(gòu)建的數(shù)據(jù)流暢訪問

相關軟件相關文章發(fā)表評論 來源:本站整理時間:2010/8/25 21:24:59字體大小:A-A+

作者:佚名點擊:68次評論:0次標簽: Sql

  • 類型:電子教程大。8.5M語言:中文 評分:8.3
  • 標簽:
立即下載

如果用數(shù)據(jù)庫做持久化設備的話直接寫sql(存儲過程)還是用ORM呢?
無疑ORM的出現(xiàn)給了我們一個全新的看待數(shù)據(jù)操作的視角:在面向?qū)ο蟮恼Z言中,用面向?qū)ο蟮姆椒ㄔL問,操作數(shù)據(jù)
但是在使用ORM一段時間后,總是會覺得有點別扭的地方,因為關系型數(shù)據(jù)庫對數(shù)據(jù)的抽象方式是基于關系代數(shù)的層次結(jié)構(gòu),而對象化的數(shù)據(jù)抽象方式是網(wǎng)狀結(jié)構(gòu),ORM在這兩種抽象模式之間映射就會產(chǎn)生Impedance Mismatch(阻抗不匹配)的現(xiàn)象,所以在映射不當?shù)臅r候就會感覺非常的別扭。
那么我再想,如果抽象數(shù)據(jù)本身存在阻抗不匹配的問題,那么如果我們抽象對數(shù)據(jù)的訪問呢?無論如何ORM,對關系數(shù)據(jù)庫的訪問仍然是通過SQL語句作為訪問的界面,那么如果我們抽象SQL語句是否就能擺脫阻抗失調(diào),能夠流暢的訪問操作數(shù)據(jù)了呢?我在上一篇文章發(fā)布的一個Python的DAL里做了一個小小的嘗試,當然我并不是第一個這么做的人,不過我想把這種方法總結(jié)出來,也許能夠在ORM以外提供一個更新的視角,能夠產(chǎn)生出更加輕量化的數(shù)據(jù)訪問組件,也是不錯的。用Python實現(xiàn)是因為暫時我還只想到了在動態(tài)語言下如何實現(xiàn),如果需要在.NET下使用,可以用IronPython。如果有同學想到了在C#下如何實現(xiàn)也希望能夠拿出來和大家分享一下。
為什么要用動態(tài)語言來實現(xiàn),首先就是不要實體類,因為我們抽象的是訪問數(shù)據(jù)的方式而不是數(shù)據(jù)本身,在關系型數(shù)據(jù)庫里數(shù)據(jù)就是數(shù)據(jù)行,字段的形式,在數(shù)據(jù)結(jié)構(gòu)上一行數(shù)據(jù)用字典就能夠表示了,而在python下我們可以把字典用下面的形式來表現(xiàn):
class Row(dict):
def __getattr__(self,propertyName):
if self.has_key(propertyName):
return self[propertyName]
return None


這樣一個Row的對象我們就可以通過列明對應屬性來訪問其中的鍵值,就跟一個實體類一樣,這樣我們就解決了數(shù)據(jù)抽象的問題。
接下來是重點,我們要抽象SQL,首先要分析SQL的結(jié)構(gòu),我們對數(shù)據(jù)的操作有 增、刪、改、查四類,分別通過:
INSERT、DELETE、UPDATE、SELECT四種SQL語句來實現(xiàn),每一種SQL語句又由子句構(gòu)成,四種SQL語句的子句中有各自獨有到,也有共有的子句,比如WHERE子句,SELECT、UPDATE、DELETE 這三種SQL操作都有WHERE子句,且語義相同,均表示待操作的數(shù)據(jù)篩選到條件,所以我將篩選條件抽象出來定義了conds這個類。
class conds:
def __init__(self,field):
self.field_name=field
self._sql=""
self._params=[]
self._has_value=False
self._sub_conds=[]
self._no_value=False
這個類用來將語言的關系運算邏輯映射到SQL語句上,所幸的是Python支持操作符重載,所以我們只需要在conds類中加入相應的buildin方法就行了。比如:
def __eq__(self,value):
return self._prepare("".join(["`",self.field_name,"`=%s"]),value)


def _prepare(self,sql,value):
if not self._has_value:
self._sql=sql
self._params.append(value)
self._has_value=True
return self
raise OperationalError,"Multiple Operate conditions"


上面代碼就定義了如果 conds('col1')==5 就會映射到sql col1=%s 且增加一個參數(shù),值為5。
同理將其他關系操作符的方法都映射到相應的buildin方法中,兩個關系間是and和or,我們用__and__和__or__這兩個方法來映射,還有Like找不到相應的操作符,就用like方法來表示這個關系,條件操作的結(jié)果還是條件,所以要用對象本身作為返回值。這樣 (conds('col1')==5)&(conds('col2')<6) 就映射到了條件 col1=%s and col2<%s這兩個條件的并集。由于這么寫還需要用字符串來表示列名不方便,所以我們定義一個table類來獲取conds:
class TableQueryer:
'''
Support for single table simple querys
'''
def __init__(self,db,tablename):
self.tablename=tablename
self.db=db


def __call__(self,query=None):
return Operater(self.db,self.tablename,query)


def __getattr__(self,field_name):
return conds(field_name)


同理我們在數(shù)據(jù)連接類上加入getattr,
def __getattr__(self,tablename):
'''
return single table queryer for select table
'''
return TableQueryer(self,tablename)

然后我們就能夠通過db.tablename.colname來獲取條件對象了,之前的例子就能改成
(db.tablename.col1==5)&(db.tablename.col2<6)
如果預先 tb=db.tablename 的話還可以改寫成
(tb.col1==t)&(tb.col2<6)


由于插入數(shù)據(jù)只需要數(shù)據(jù)表名不需要查詢?yōu)榛A,所以直接在TableQueryer中加入insert方法
所以插入數(shù)據(jù)就只需要db.tablename.insert(col1=value1,col2=value2...)


數(shù)據(jù)的查詢、更新、刪除都是基于查詢條件的,所以抽象出一個操作對象Operate出來:
class Operater:
def __init__(self,db,tablename,query):
self.count=Count(db,tablename,query)
self.select=Select(db,tablename,query)
self.update=Update(db,tablename,query)
self.delete=Delete(db,tablename,query)


每一個操作抽象一個類出來,并且把查詢條件保存到了每一個操作的條件里,最終的Sql生成,以及特定子句的加入,都在具體的類比如Select里完成。
我在這里為了節(jié)約一個方法名的層次出來就把TableQueryer做成了可以調(diào)用的對象,加入了__call__方法。將查詢條件傳入__call__方法就返回了一個Operator對象,于是通過
tb=db.tablename
q=tb((tb.col1==5)&(tb.col2<6))
q.select()就能查詢出結(jié)果,等價sql為 select * from tablename where col1=5 and col2<6
在得到q后,直接調(diào)用q.delete()就能把這些數(shù)據(jù)刪掉
q.update(tb.col1==6)就能更新篩選出的數(shù)據(jù)
q.delete()就能直接刪掉符合篩選條件的數(shù)據(jù)

項目放在 http://bitbucket.org/alexander_lee/flunt-sql-data-access-layer

    相關評論

    閱讀本文后您有什么感想? 已有人給出評價!

    • 8 喜歡喜歡
    • 3 頂
    • 1 難過難過
    • 5 囧
    • 3 圍觀圍觀
    • 2 無聊無聊

    熱門評論

    最新評論

    發(fā)表評論 查看所有評論(0)

    昵稱:
    表情: 高興 可 汗 我不要 害羞 好 下下下 送花 屎 親親
    字數(shù): 0/500 (您的評論需要經(jīng)過審核才能顯示)