2012-07-09 62 views
0

我想弄清楚如何使用QxOrm來堅持一個龐大而複雜的類結構。我已經取得了一些進展,但是我一直在關注如何處理抽象類的指針。QxOrm是否可以堅持指向抽象類的指針?

這裏有一個簡單的例子,其中表(具體類)有一個指針指向某種形狀的(一個抽象類):

class Table { 
    Shape* top; 
}; 

class Shape { 
public: 
    virtual float getWidth() = 0; 
}; 

class Square : public Shape { 
    virtual float getWidth(); 
}; 

class Circle : public Shape { 
    virtual float getWidth(); 
}; 

我收到錯誤消息,抱怨形狀是抽象的,當我嘗試這。

它看起來像我這樣做是不可能與QxOrm,我懷疑,因爲它的唯一繼承模型是混凝土。

有誰知道這是否可行?我寧願不放棄QxOrm,因爲它在許多方面看起來不錯(我已經投入了大量時間),但看起來我不得不這樣做。

更新1:我知道QX_REGISTER_ABSTRACT_CLASS。這對這個用例沒有幫助。

Update2:我嘗試在qxBlog示例摘要中製作comment類。我做了它的子類qx::IxPersistable並使用了QX_REGISTER_ABSTRACT_CLASS宏。當我編譯,它死在宏QX_PERSISTABLE_CPP的調用,具有:

../../../QxOrm/include/QxDao/../../inl/QxDao/QxDao_Count.inl:36: error: cannot declare variable 't' to be of abstract type 'comment'

還有從其他地方類似的錯誤消息,太。

(順便說一句,我會先問上QxOrm論壇,但當時無法使用。)

謝謝!

+0

你用'QX_REG ISTER_ABSTRACT_CLASS'? – 2012-07-09 17:33:52

+0

是的,謝謝你的提示。看起來'QX_REGISTER_ABSTRACT_CLASS'可以讓你聲明數據字段,然後成爲具體後代表的一部分。但它不能解決我的問題。 – Chris 2012-07-10 02:35:24

回答

0

要註冊一個抽象類爲QxOrm方面:http://www.qxorm.com/qxorm_en/faq.html#faq_140

而且隨着指針的基類的工作,我認爲QX :: IxPersistable界面可以幫助你:http://www.qxorm.com/qxorm_en/faq.html#faq_260

注: QxOrm論壇現在可用...

+0

我知道'QX_REGISTER_ABSTRACT_CLASS'。我閱讀了'qx :: IxPersistable',但它看起來不像是對這種情況是必要的或有用的。不過,我會嘗試。並感謝關於論壇的提示。 – Chris 2012-07-10 16:10:18

0

這裏是一個通用的解決方案,使用qx :: IxPersistable接口和QxOrm觸發器。 這個想法是存儲你的基類的ID和與你ID相關的類型:這樣,你將能夠實例化所有的派生類。

--- MyBaseClass.h文件:

class QX_DLL2_EXPORT MyBaseClass : public qx::IxPersistable 
{ 

public: 

    long id; 

    MyBaseClass() : qx::IxPersistable(), id(0) { ; } 
    virtual ~MyBaseClass() = 0; 

}; 

QX_REGISTER_ABSTRACT_CLASS(MyBaseClass) 
QX_REGISTER_HPP_QX_DLL2(MyBaseClass, qx::trait::no_base_class_defined, 0) 

typedef boost::shared_ptr<MyBaseClass> MyBaseClass_ptr; 

--- MyDerivedClass1.h文件:

class QX_DLL2_EXPORT MyDerivedClass1 : public MyBaseClass 
{ 

    QX_PERSISTABLE_HPP(MyDerivedClass1) 

public: 

    QString description; 

    MyDerivedClass1() : MyBaseClass() { ; } 
    virtual ~MyDerivedClass1() { ; } 

}; 

QX_REGISTER_HPP_QX_DLL2(MyDerivedClass1, MyBaseClass, 0) 

typedef boost::shared_ptr<MyDerivedClass1> MyDerivedClass1_ptr; 

--- MyDerivedClass2.h文件:

class QX_DLL2_EXPORT MyDerivedClass2 : public MyBaseClass 
{ 

    QX_PERSISTABLE_HPP(MyDerivedClass2) 

public: 

    QString prop1; 
    QString prop2; 

    MyDerivedClass2() : MyBaseClass() { ; } 
    virtual ~MyDerivedClass2() { ; } 

}; 

QX_REGISTER_HPP_QX_DLL2(MyDerivedClass2, MyBaseClass, 0) 

typedef boost::shared_ptr<MyDerivedClass2> MyDerivedClass2_ptr; 

--- MyContainer。^ h文件:

class QX_DLL2_EXPORT MyContainer 
{ 

public: 

    long id; 

    long base_id; 
    QString base_type; 
    MyBaseClass_ptr base_ptr; 

    MyContainer() : id(0), base_id(0) { ; } 
    virtual ~MyContainer() { ; } 

    void onBeforeInsert(qx::dao::detail::IxDao_Helper * dao); 
    void onBeforeUpdate(qx::dao::detail::IxDao_Helper * dao); 
    void onBeforeDelete(qx::dao::detail::IxDao_Helper * dao); 
    void onBeforeFetch(qx::dao::detail::IxDao_Helper * dao); 
    void onAfterInsert(qx::dao::detail::IxDao_Helper * dao); 
    void onAfterUpdate(qx::dao::detail::IxDao_Helper * dao); 
    void onAfterDelete(qx::dao::detail::IxDao_Helper * dao); 
    void onAfterFetch(qx::dao::detail::IxDao_Helper * dao); 

    void insertOrUpdateBasePtr(qx::dao::detail::IxDao_Helper * dao); 

}; 

QX_REGISTER_HPP_QX_DLL2(MyContainer, qx::trait::no_base_class_defined, 0) 

typedef boost::shared_ptr<MyContainer> MyContainer_ptr; 

namespace qx { 
namespace dao { 
namespace detail { 

template <> 
struct QxDao_Trigger<MyContainer> 
{ 

    static inline void onBeforeInsert(MyContainer * t, qx::dao::detail::IxDao_Helper * dao) { if (t) { t->onBeforeInsert(dao); } } 
    static inline void onBeforeUpdate(MyContainer * t, qx::dao::detail::IxDao_Helper * dao) { if (t) { t->onBeforeUpdate(dao); } } 
    static inline void onBeforeDelete(MyContainer * t, qx::dao::detail::IxDao_Helper * dao) { if (t) { t->onBeforeDelete(dao); } } 
    static inline void onBeforeFetch(MyContainer * t, qx::dao::detail::IxDao_Helper * dao) { if (t) { t->onBeforeFetch(dao); } } 
    static inline void onAfterInsert(MyContainer * t, qx::dao::detail::IxDao_Helper * dao) { if (t) { t->onAfterInsert(dao); } } 
    static inline void onAfterUpdate(MyContainer * t, qx::dao::detail::IxDao_Helper * dao) { if (t) { t->onAfterUpdate(dao); } } 
    static inline void onAfterDelete(MyContainer * t, qx::dao::detail::IxDao_Helper * dao) { if (t) { t->onAfterDelete(dao); } } 
    static inline void onAfterFetch(MyContainer * t, qx::dao::detail::IxDao_Helper * dao)  { if (t) { t->onAfterFetch(dao); } } 

}; 

} // namespace detail 
} // namespace dao 
} // namespace qx 

--- MyBaseClass.cpp文件:

QX_REGISTER_CPP_QX_DLL2(MyBaseClass) 

namespace qx { 
template <> void register_class(QxClass<MyBaseClass> & t) 
{ 
    t.id(& MyBaseClass::id, "id"); 
}} 

MyBaseClass::~MyBaseClass() { ; } 

--- MyDerivedClass1.cpp文件:

QX_REGISTER_CPP_QX_DLL2(MyDerivedClass1) 
QX_PERSISTABLE_CPP(MyDerivedClass1) 

namespace qx { 
template <> void register_class(QxClass<MyDerivedClass1> & t) 
{ 
    t.data(& MyDerivedClass1::description, "description"); 
}} 

--- MyDerivedClass2 .cpp file:

QX_REGISTER_CPP_QX_DLL2(MyDerivedClass2) 
QX_PERSISTABLE_CPP(MyDerivedClass2) 

namespace qx { 
template <> void register_class(QxClass<MyDerivedClass2> & t) 
{ 
    t.data(& MyDerivedClass2::prop1, "prop1"); 
    t.data(& MyDerivedClass2::prop2, "prop2"); 
}} 

--- MyContainer.cpp文件:

QX_REGISTER_CPP_QX_DLL2(MyContainer) 

namespace qx { 
template <> void register_class(QxClass<MyContainer> & t) 
{ 
    t.id(& MyContainer::id, "id"); 
    t.data(& MyContainer::base_id, "base_id"); 
    t.data(& MyContainer::base_type, "base_type"); 
}} 

void MyContainer::onBeforeInsert(qx::dao::detail::IxDao_Helper * dao) 
{ 
    if (! dao) { qAssert(false); return; } 
    if (dao->error().isValid()) { return; } 
    if (! base_ptr || ! base_ptr->qxClass()) { return; } 

    base_id = base_ptr->id; 
    base_type = base_ptr->qxClass()->getKey(); 
} 

void MyContainer::onBeforeUpdate(qx::dao::detail::IxDao_Helper * dao) 
{ 
    if (! dao) { qAssert(false); return; } 
    if (dao->error().isValid()) { return; } 
    if (! base_ptr || ! base_ptr->qxClass()) { return; } 

    base_id = base_ptr->id; 
    base_type = base_ptr->qxClass()->getKey(); 
} 

void MyContainer::onBeforeDelete(qx::dao::detail::IxDao_Helper * dao) 
{ 
    if (! dao) { qAssert(false); return; } 
    if (dao->error().isValid()) { return; } 
    // Nothing to do here ! 
} 

void MyContainer::onBeforeFetch(qx::dao::detail::IxDao_Helper * dao) 
{ 
    if (! dao) { qAssert(false); return; } 
    if (dao->error().isValid()) { return; } 
    // Nothing to do here ! 
} 

void MyContainer::onAfterInsert(qx::dao::detail::IxDao_Helper * dao) 
{ 
    if (! dao) { qAssert(false); return; } 
    if (dao->error().isValid()) { return; } 
    insertOrUpdateBasePtr(dao); 
} 

void MyContainer::onAfterUpdate(qx::dao::detail::IxDao_Helper * dao) 
{ 
    if (! dao) { qAssert(false); return; } 
    if (dao->error().isValid()) { return; } 
    insertOrUpdateBasePtr(dao); 
} 

void MyContainer::onAfterDelete(qx::dao::detail::IxDao_Helper * dao) 
{ 
    if (! dao) { qAssert(false); return; } 
    if (dao->error().isValid()) { return; } 

    if (base_ptr) 
    { 
     QVariant idEmpty; 
     QSqlError daoError = base_ptr->qxDeleteById(idEmpty, (& dao->database())); 
     dao->updateError(daoError); 
    } 
} 

void MyContainer::onAfterFetch(qx::dao::detail::IxDao_Helper * dao) 
{ 
    if (! dao) { qAssert(false); return; } 
    if (dao->error().isValid()) { return; } 

    if ((base_id > 0) && (! base_type.isEmpty())) 
    { 
     MyBaseClass * pBase = qx::create_nude_ptr<MyBaseClass>(base_type); 
     if (! pBase) { qAssert(false); return; } 
     base_ptr.reset(pBase); 
     QVariant vId = base_id; QStringList lstEmpty; 
     QSqlError daoError = base_ptr->qxFetchById(vId, lstEmpty, lstEmpty, (& dao->database())); 
     dao->updateError(daoError); 
    } 
} 

void MyContainer::insertOrUpdateBasePtr(qx::dao::detail::IxDao_Helper * dao) 
{ 
    static bool bInEvent = false; 
    if (! base_ptr || bInEvent) { return; } 
    bInEvent = true; 

    QStringList lstEmpty; QVariant idEmpty; 
    QSqlError daoError; qx::QxSqlQuery queryEmpty; 
    qx_bool bExist = base_ptr->qxExist(idEmpty, (& dao->database())); 
    if (bExist) 
    { 
     daoError = base_ptr->qxUpdate(queryEmpty, lstEmpty, lstEmpty, (& dao->database())); 
     dao->updateError(daoError); 
    } 
    else 
    { 
     daoError = base_ptr->qxInsert(lstEmpty, (& dao->database())); 
     if (! daoError.isValid()) { daoError = qx::dao::update((* this), (& dao->database()), QStringList() << "base_id" << "base_type"); } 
     dao->updateError(daoError); 
    } 

    bInEvent = false; 
} 

--- 的main.cpp文件做一些測試:

daoError = qx::dao::create_table<MyDerivedClass1>(); qAssert(! daoError.isValid()); 
    daoError = qx::dao::create_table<MyDerivedClass2>(); qAssert(! daoError.isValid()); 
    daoError = qx::dao::create_table<MyContainer>(); qAssert(! daoError.isValid()); 

    MyContainer b1; 
    MyDerivedClass1_ptr pD1 = MyDerivedClass1_ptr(new MyDerivedClass1()); 
    pD1->description = "my desc"; 
    b1.base_ptr = pD1; 
    daoError = qx::dao::insert(b1); qAssert(! daoError.isValid()); 

    MyContainer b2; 
    MyDerivedClass2_ptr pD2 = MyDerivedClass2_ptr(new MyDerivedClass2()); 
    pD2->prop1 = "my prop1"; 
    pD2->prop2 = "my prop2"; 
    b2.base_ptr = pD2; 
    daoError = qx::dao::insert(b2); qAssert(! daoError.isValid()); 

    MyContainer b3; 
    b3.base_ptr = pD1; 
    pD1->description = "my desc modified"; 
    daoError = qx::dao::insert(b3); qAssert(! daoError.isValid()); 

    QList<MyContainer_ptr> all; 
    daoError = qx::dao::fetch_all(all); 
    qx::dump(all); 

而且所有輸出的痕跡:

[QxOrm] sql query (0 ms) : CREATE TABLE MyDerivedClass1 (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, description TEXT) 
[QxOrm] sql query (0 ms) : CREATE TABLE MyDerivedClass2 (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, prop1 TEXT, prop2 TEXT) 
[QxOrm] sql query (16 ms) : CREATE TABLE MyContainer (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, base_id INTEGER, base_type TEXT) 
[QxOrm] sql query (0 ms) : SELECT MyDerivedClass1.id AS MyDerivedClass1_id_0 FROM MyDerivedClass1 WHERE MyDerivedClass1.id = :id 
[QxOrm] sql query (0 ms) : INSERT INTO MyDerivedClass1 (description) VALUES (:description) 
[QxOrm] sql query (0 ms) : UPDATE MyContainer SET id = :id, base_id = :base_id, base_type = :base_type WHERE id = :id_bis 
[QxOrm] sql query (3245 ms) : INSERT INTO MyContainer (base_id, base_type) VALUES (:base_id, :base_type) 
[QxOrm] sql query (0 ms) : SELECT MyDerivedClass2.id AS MyDerivedClass2_id_0 FROM MyDerivedClass2 WHERE MyDerivedClass2.id = :id 
[QxOrm] sql query (0 ms) : INSERT INTO MyDerivedClass2 (prop1, prop2) VALUES (:prop1, :prop2) 
[QxOrm] sql query (0 ms) : UPDATE MyContainer SET id = :id, base_id = :base_id, base_type = :base_type WHERE id = :id_bis 
[QxOrm] sql query (0 ms) : INSERT INTO MyContainer (base_id, base_type) VALUES (:base_id, :base_type) 
[QxOrm] sql query (0 ms) : SELECT MyDerivedClass1.id AS MyDerivedClass1_id_0 FROM MyDerivedClass1 WHERE MyDerivedClass1.id = :id 
[QxOrm] sql query (0 ms) : UPDATE MyDerivedClass1 SET id = :id, description = :description WHERE id = :id_bis 
[QxOrm] sql query (15 ms) : INSERT INTO MyContainer (base_id, base_type) VALUES (:base_id, :base_type) 
[QxOrm] sql query (0 ms) : SELECT MyDerivedClass1.id AS MyDerivedClass1_id_0, MyDerivedClass1.description AS MyDerivedClass1_description_0 FROM MyDerivedClass1 WHERE MyDerivedClass1.id = :id 
[QxOrm] sql query (0 ms) : SELECT MyDerivedClass2.id AS MyDerivedClass2_id_0, MyDerivedClass2.prop1 AS MyDerivedClass2_prop1_0, MyDerivedClass2.prop2 AS MyDerivedClass2_prop2_0 FROM MyDerivedClass2 WHERE MyDerivedClass2.id = :id 
[QxOrm] sql query (0 ms) : SELECT MyDerivedClass1.id AS MyDerivedClass1_id_0, MyDerivedClass1.description AS MyDerivedClass1_description_0 FROM MyDerivedClass1 WHERE MyDerivedClass1.id = :id 
[QxOrm] sql query (0 ms) : SELECT MyContainer.id AS MyContainer_id_0, MyContainer.base_id AS MyContainer_base_id_0, MyContainer.base_type AS MyContainer_base_type_0 FROM MyContainer 
[QxOrm] start dump 'QList<boost::shared_ptr<MyContainer>>' 
<QList-boost.shared_ptr-MyContainer-- class_id="0" tracking_level="0" version="0"> 
    <count>3</count> 
    <item class_id="1" tracking_level="0" version="1"> 
     <px class_id="2" tracking_level="1" version="0" object_id="_0"> 
     <id>1</id> 
     <base_id>1</base_id> 
     <base_type class_id="3" tracking_level="0" version="0">MyDerivedClass1</base_type> 
     <base_ptr class_id="4" tracking_level="0" version="1"> 
      <px class_id="6" class_name="MyDerivedClass1" tracking_level="1" version="0" object_id="_1"> 
       <MyBaseClass class_id="5" tracking_level="1" version="0" object_id="_2"> 
        <id>1</id> 
       </MyBaseClass> 
       <description>my desc modified</description> 
      </px> 
     </base_ptr> 
     </px> 
    </item> 
    <item> 
     <px class_id_reference="2" object_id="_3"> 
     <id>2</id> 
     <base_id>1</base_id> 
     <base_type>MyDerivedClass2</base_type> 
     <base_ptr> 
      <px class_id="7" class_name="MyDerivedClass2" tracking_level="1" version="0" object_id="_4"> 
       <MyBaseClass object_id="_5"> 
        <id>1</id> 
       </MyBaseClass> 
       <prop1>my prop1</prop1> 
       <prop2>my prop2</prop2> 
      </px> 
     </base_ptr> 
     </px> 
    </item> 
    <item> 
     <px class_id_reference="2" object_id="_6"> 
     <id>3</id> 
     <base_id>1</base_id> 
     <base_type>MyDerivedClass1</base_type> 
     <base_ptr> 
      <px class_id_reference="6" object_id="_7"> 
       <MyBaseClass object_id="_8"> 
        <id>1</id> 
       </MyBaseClass> 
       <description>my desc modified</description> 
      </px> 
     </base_ptr> 
     </px> 
    </item> 
</QList-boost.shared_ptr-MyContainer--> 
[QxOrm] end dump 'QList<boost::shared_ptr<MyContainer>>' 
相關問題