2012-07-09 61 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>>' 
相关问题