本節主要介紹ODB中的繼承和C++之間的關係。 數據庫
ORM中的O的關係是很複雜的。其中之一即是對象的繼承體系。 佈局
在C++語言中支持類之間的繼承,這這些繼承的關係是否能夠同時映射到數據庫呢? spa
ODB支持2中繼承類型,abstract和polymorphic。根據ODB文檔的描述,abstract方式爲複用繼承。而polymorphic是屬於虛擬繼承(支持C++的動態聯編). 對象
咱們知道,要把一個C++類定義爲數據庫對象,須要使用#pragma db object 指令告訴ODB編譯器。而abstract和polymorphic都是object的一種模式,所以須要使用指令#pragma db object abstract 或者#pragma db object polymorphic指令來通知編譯器,基類的繼承模型。 繼承
abstract和polymorphic在同一個基類中是不能共存的,要不選擇abstract要不就選擇polymorphic。 事件
從數據庫的表現來看,abstract對應的object類,ODB沒有爲其生成對應的表格,很驚訝吧,不是說每一個object類都至少會映射一個表格嗎?怎麼abstract object沒有呢?由於派生類僅僅是把abstract 類的字段合併到本身的表格中而已,有點很想C++的POD類型,僅僅是內存佈局上合併在一塊兒,只不過在這裏是合併在同一個表格上。 內存
另外abstract object不能有 標記爲id屬性的字段。由於他不是一個數據庫持久對象。也不能使用load、persist、update、find、erase等數據庫方法直接操做abstract object類對象。 文檔
polymorphic的行爲和C++的動態類型幾乎是同樣的。ODB會爲polymorphic的基類生成一個獨立的表格,裏面會包含子類的類型信息。polymorphic能夠有id屬性,整個繼承體系的id在相同的線性空間上,也就是不一樣派生類的對象的id不能相同。在load、find的時候,會根據數據庫表格裏面存儲的類類型自動建立正確的子類。在persist、update、erase的時候,也能夠直接只用polymorphic的基類調用便可,ODB生成的代碼會自動的去識別子類的類型,並調用相應的trait類。 編譯器
ODB文檔描述:polymorphic的表格有三種方式分別爲table-per-hierarchy, table-per-difference, and table-per-class 同步
table-per-hierarchy: 就是每一個polymorphic類及其派生類共用一個表格。大表,對於不相關的字段賦值爲NULL。
table-per-difference: 就是polymorphic基類有一個表格,讓後每一個派生類也有本身的一個表格,派生類的表格只保存與本身像個的字段,不保存基類的字段。可是這樣有個問題,就是在load對象的時候須要使用聯合查詢或者2次查詢。在update,persist的時候須要2或者多條SQL語句。(推薦使用、數據庫沒有太多的冗餘字段)
table-per-class: 每一個派生類一個表格,而且把基類的信息一塊兒合併在一塊兒。和abstract的派生類的表格相似。
polymorphic特性實在ODB1.8版本才引入的。早期1.4,1.5版本只支持abstract模式。這個時候ODB本身不支持動態類型,須要本身額外添加一個關聯映射對象,除了類名稱,字段和abstract類如出一轍,而且本身增長類型信息字段。在dbevent的persist、erase事件的時候,同步操做關聯類,相對比較麻煩。
使用入門(一)的數據模型;
加上數據庫id爲1的類型爲一個Zone類。那麼一下2中方式均可以正確的從數據庫加載Zone的信息.
shared_ptr<Zone> z = db.load<Zone>(1);
shared_ptr<Entity> e = db.load<Entity>(1);
persist時, shared_ptr<Zone> z( new Zone()) 或者 shared_ptr<Entity>(new Zone());均可以直接調用db.persist(z). update、erase與persist相同。
不能在abstract類上調用persist\update\erase等操做.