為了避免sql注入或白盒漏洞問題,同時也是為了方便資料底層操作,工作中會盡量避免使用原生sql,而選擇orm。python中常用的有sqlalchemy庫。該庫的使用可以學習參考
在使用過程中會發現需要自行建立乙個class去對映資料表結構,然後通過操作class進行資料的增刪改查等一系列操作。這個其實已經能滿足日常的使用,但是在工作中我們常會選擇資料分離,分工明確, 比如我就遇到需要設計底層dal,提供統一的資料介面給所有業務,我們可以選擇讓業務線把設計好的表結構或者建立語句統一給我們,然後儲存乙個py檔案去維護這些表資訊,將表結構對映成model。
這種做法有以下幾個問題:
修改表結構資訊,需要動態修改py檔案
業務線修改表結構可能不能完全同步到dal層,導致業務邏輯出現癱瘓
對於線上環境,每次修改都需要重新部署上線,這是乙個浪費人力和時間的事情,而且不能保證完全不出錯。
基於以上考慮,我們會考慮,如何動態獲取資料庫中表結構的變化,這就是所謂的資料表反射成實體類(起初不知道這個概念,只能查詢資料:如何動態生成資料表的model類)。
查詢資料,首先看到的是使用sqlacodegen方法,建議參考部落格:起初使用這種方法在本地確實可以方便的生成所有實體類,並生成model檔案,然後獲取檔案中的所有class,最後我們就可以通過表名獲取到對應的實體類,然後進行orm操作
def get_classes(module_name=storage.db_models) -> dict:
# 獲取db_models檔案 中所有類物件
classes =
table = {}
file = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + '/storage/' + 'db_models.py'
if not os.path.exists(file):
return table
ret = inspect.getmembers(module_name, inspect.isclass)
try:
for name, class_ in ret:
if '__tablename__' in dir(class_):
table[class_.__tablename__] = class_
except exception as e:
logging(e, exc_info=true)
return table
缺點:
通過ip+port的形式連線資料庫,在本地可操作,線上不一定會被允許,例如我們公司不允許使用ip+port的形式連線,封裝了自己的mysql庫,導致上線失敗
需要定時的去執行sqlacodegen命令,保證獲取的model檔案是最新的
強烈推薦使用這種方法
真是寶藏方法,解決了很大一麻煩,具體可以參考這篇部落格,裡面有三種方法 下面展示自己寫的偽**:親測是有效的,可以動態感知資料表結構變化
def create_model(self):
"""反射資料表為實體類"""
engine = sqlalchemyengine()._engine # 建立資料庫引擎,可以根據具體情況操作,不用擔心線上線下環境影響,和普通連線資料庫建立引擎方法相同
base = automap_base()
base.prepare(engine, reflect=true)
base.classes.keys() # 獲取所有的物件名
return base.classes
def test():
table = self.create_table()
table_name = 'test_example『 # 資料庫表名
model = table[table_name]
ret = s.query(model).filter_by(**condition).update(data) # 進行orm操作
通過這次事件,以後即使不做dal層,只寫業務**,也會選擇這種方法,不會呆板地維護自己的model類了,雖然對於熟悉業務的個人來說改造比較方便成本不大,但是如果進行業務交接就很麻煩了,保持乙個原則:能動態感知的盡量使用動態方法感知,能少改動**的少改動,能不重新上線的不上線。 根據SQLServer資料表生成C 實體類
生成表的實體類工具,有助於減少 量,加快開發速度.第一副圖根據輸入的連線伺服器位址 使用者名稱 登入資料庫名 密碼連線到資料庫.如果錯誤則提示連線失敗.第二幅圖先取的當前資料庫所有的使用者建立的表 然後根據選中的表名取得資料庫中關於此表資訊的的系統表.然後將字段型別轉換為c 資料型別.並輸出的tex...
利用反射將資料讀入實體類
利用反射將資料讀入實體類 在實際開發中,我們經常需要從資料庫中讀取資料並賦值給實體類的相應屬性。比如 public role getroles int blogid if reader name dbnull.value if reader description dbnull.value read...
java通過實體類名稱獲取對應的資料表名稱
entity name x 指定的是實體名稱,不是表名,但是實體名稱會影響生成的表名 根據命名約定 表名可能也是 x了。如要明確指定表名需要附加乙個 table 如果想根據類名拿到註解裡面的name屬性,可以用反射來做 class cls class.forname com.papapa.x 或直接...