日本好好热aⅴ|国产99视频精品免费观看|日本成人aV在线|久热香蕉国产在线

  • <cite id="ikgdy"><table id="ikgdy"></table></cite>
    1. 西西軟件園多重安全檢測下載網(wǎng)站、值得信賴的軟件下載站!
      軟件
      軟件
      文章
      搜索

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

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

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

      作者:佚名點(diǎn)擊:68次評(píng)論:0次標(biāo)簽: Sql

      • 類型:電子教程大。8.5M語言:中文 評(píng)分:8.3
      • 標(biāo)簽:
      立即下載

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


      這樣一個(gè)Row的對(duì)象我們就可以通過列明對(duì)應(yīng)屬性來訪問其中的鍵值,就跟一個(gè)實(shí)體類一樣,這樣我們就解決了數(shù)據(jù)抽象的問題。
      接下來是重點(diǎn),我們要抽象SQL,首先要分析SQL的結(jié)構(gòu),我們對(duì)數(shù)據(jù)的操作有 增、刪、改、查四類,分別通過:
      INSERT、DELETE、UPDATE、SELECT四種SQL語句來實(shí)現(xiàn),每一種SQL語句又由子句構(gòu)成,四種SQL語句的子句中有各自獨(dú)有到,也有共有的子句,比如WHERE子句,SELECT、UPDATE、DELETE 這三種SQL操作都有WHERE子句,且語義相同,均表示待操作的數(shù)據(jù)篩選到條件,所以我將篩選條件抽象出來定義了conds這個(gè)類。
      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
      這個(gè)類用來將語言的關(guān)系運(yùn)算邏輯映射到SQL語句上,所幸的是Python支持操作符重載,所以我們只需要在conds類中加入相應(yīng)的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 就會(huì)映射到sql col1=%s 且增加一個(gè)參數(shù),值為5。
      同理將其他關(guān)系操作符的方法都映射到相應(yīng)的buildin方法中,兩個(gè)關(guān)系間是and和or,我們用__and__和__or__這兩個(gè)方法來映射,還有Like找不到相應(yīng)的操作符,就用like方法來表示這個(gè)關(guān)系,條件操作的結(jié)果還是條件,所以要用對(duì)象本身作為返回值。這樣 (conds('col1')==5)&(conds('col2')<6) 就映射到了條件 col1=%s and col2<%s這兩個(gè)條件的并集。由于這么寫還需要用字符串來表示列名不方便,所以我們定義一個(gè)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)


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

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


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


      數(shù)據(jù)的查詢、更新、刪除都是基于查詢條件的,所以抽象出一個(gè)操作對(duì)象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)


      每一個(gè)操作抽象一個(gè)類出來,并且把查詢條件保存到了每一個(gè)操作的條件里,最終的Sql生成,以及特定子句的加入,都在具體的類比如Select里完成。
      我在這里為了節(jié)約一個(gè)方法名的層次出來就把TableQueryer做成了可以調(diào)用的對(duì)象,加入了__call__方法。將查詢條件傳入__call__方法就返回了一個(gè)Operator對(duì)象,于是通過
      tb=db.tablename
      q=tb((tb.col1==5)&(tb.col2<6))
      q.select()就能查詢出結(jié)果,等價(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ù)

      項(xiàng)目放在 http://bitbucket.org/alexander_lee/flunt-sql-data-access-layer

        相關(guān)評(píng)論

        閱讀本文后您有什么感想? 已有人給出評(píng)價(jià)!

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

        熱門評(píng)論

        最新評(píng)論

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

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