C++ QxOrm能否持久化指向抽象类的指针?

C++ QxOrm能否持久化指向抽象类的指针?,c++,persistence,qxorm,C++,Persistence,Qxorm,我试图弄清楚如何使用来持久化一个大型的、复杂的类结构。我已经取得了一些进展,但仍停留在如何处理指向抽象类的指针上 下面是一个简单的示例,其中Table(一个具体的类)有一个指向某种形状(一个抽象类)的指针: 当我尝试此操作时,会收到错误消息,抱怨形状是抽象的 在我看来,QxOrm不可能做到这一点,我怀疑这是因为它唯一的继承模型是具体的 有人知道这是否可能吗?我不想放弃QxOrm,因为它在很多方面看起来都不错(我已经花了很多时间在它上面了),但看起来我不得不放弃 Update1:我知道QX\u R

我试图弄清楚如何使用来持久化一个大型的、复杂的类结构。我已经取得了一些进展,但仍停留在如何处理指向抽象类的指针上

下面是一个简单的示例,其中Table(一个具体的类)有一个指向某种形状(一个抽象类)的指针:

当我尝试此操作时,会收到错误消息,抱怨形状是抽象的

在我看来,QxOrm不可能做到这一点,我怀疑这是因为它唯一的继承模型是具体的

有人知道这是否可能吗?我不想放弃QxOrm,因为它在很多方面看起来都不错(我已经花了很多时间在它上面了),但看起来我不得不放弃


Update1:我知道
QX\u REGISTER\u ABSTRACT\u CLASS
。它对这个用例没有帮助

Update2:我尝试在qxBlog示例摘要中创建
comment
类。我使它成为子类
qx::IxPersistable
,并使用
qx\u REGISTER\u ABSTRACT\u类
宏。当我编译时,它会在调用宏
QX\u PERSISTABLE\u CPP
时消失,带有:

../../../QxOrm/include/QxDao/../../inl/QxDao/QxDao_Count.inl:36:错误:无法将变量“t”声明为抽象类型“comment”

其他地方也有类似的错误消息

(顺便说一句,我本打算先在QxOrm论坛上提问,但当时没有。)


谢谢

要将抽象类注册到QxOrm上下文中:

为了使用指向基类的指针,我认为qx::IxPersistable接口可以帮助您:


注意:QxOrm论坛现在可用…

这里是一个使用qx::IxPersistable接口和QxOrm触发器的通用解决方案。 其思想是存储基类的ID+与ID相关联的类型:这样,您将能够实例化所有派生类

---MyBaseClass.h文件:

类QX_DLL2_导出MyBaseClass:public QX::IxPersistable { 公众: 长id; MyBaseClass():qx::IxPersistable(),id(0){;} virtual~MyBaseClass()=0; }; QX_寄存器_抽象_类(MyBaseClass) QX_寄存器_HPP_QX_DLL2(MyBaseClass,QX::trait::未定义基本类,0) typedef boost::shared_ptr MyBaseClass_ptr; ---MyDerivedClass1.h文件:

类QX\U DLL2\U导出MyDerivedClass1:公共MyBaseClass { QX_持久性_水电站(MyDerivedClass1) 公众: QString描述; MyDerivedClass1():MyBaseClass(){;} 虚拟~MyDerivedClass1(){;} }; QX_寄存器_HPP_QX_DLL2(MyDerivedClass1,MyBaseClass,0) typedef boost::shared_ptr MyDerivedClass1_ptr; ---MyDerivedClass2.h文件:

类QX\U DLL2\U导出MyDerivedClass2:公共MyBaseClass { QX_持久性_水电站(MyDerivedClass2) 公众: QString prop1; QString-prop2; MyDerivedClass2():MyBaseClass(){;} 虚拟~MyDerivedClass2(){;} }; QX_寄存器HPP_QX_DLL2(MyDerivedClass2,MyBaseClass,0) typedef boost::shared_ptr MyDerivedClass2_ptr; ---MyContainer.h文件:

QX类DLL2类导出容器
{
公众:
长id;
长碱基;
QString基本类型;
MyBaseClass_ptr base_ptr;
MyContainer():id(0),base_id(0){;}
虚拟~MyContainer(){;}
void onbeforeensert(qx::dao::detail::IxDao\u Helper*dao);
更新前作废(qx::dao::detail::IxDao\u Helper*dao);
void onBeforeDelete(qx::dao::detail::IxDao\u Helper*dao);
void onBeforeFetch(qx::dao::detail::IxDao\u Helper*dao);
void onAfterInsert(qx::dao::detail::IxDao\u Helper*dao);
更新后无效(qx::dao::detail::IxDao\u Helper*dao);
void onAfterDelete(qx::dao::detail::IxDao\u Helper*dao);
void onAfterFetch(qx::dao::detail::IxDao\u Helper*dao);
void insertOrUpdateBasePtr(qx::dao::detail::IxDao\u Helper*dao);
};
QX_寄存器HPP_QX_DLL2(MyContainer,QX::trait::未定义基本类,0)
typedef boost::shared_ptr MyContainer_ptr;
名称空间qx{
名称空间dao{
名称空间详细信息{
模板
结构QxDao_触发器
{
静态内联void onbeforeeinsert(MyContainer*t,qx::dao::detail::IxDao_Helper*dao){if(t){t->onbeforeeinsert(dao);}
静态内联void onBeforeUpdate(MyContainer*t,qx::dao::detail::IxDao_Helper*dao){if(t){t->onBeforeUpdate(dao);}
静态内联void onBeforeDelete(MyContainer*t,qx::dao::detail::IxDao_Helper*dao){if(t){t->onBeforeDelete(dao);}
静态内联void onBeforeFetch(MyContainer*t,qx::dao::detail::IxDao_Helper*dao){if(t){t->onBeforeFetch(dao);}
AfterInsert上的静态内联void(MyContainer*t,qx::dao::detail::IxDao_Helper*dao){if(t){t->onAfterInsert(dao);}
更新后的静态内联void(MyContainer*t,qx::dao::detail::IxDao_Helper*dao){if(t){t->onAfterUpdate(dao);}
在afterdelete上的静态内联void(MyContainer*t,qx::dao::detail::IxDao_Helper*dao){if(t){t->onAfterDelete(dao);}
在afterfetch上的静态内联void(MyContainer*t,qx::dao::detail::IxDao_Helper*dao){if(t){t->onAfterFetch(dao);}
};
}//名称空间详细信息
}//名称空间dao
}//名称空间qx
---MyBaseClass.cpp文件:

QX\u寄存器\u CPP\u QX\u DLL2(MyBaseClass)
名称空间qx{
模板无效寄存器类(QxClass&t)
{
t、 id(&MyBaseClass::id,“id”);
}}
MyBaseClass::~MyBaseClass(){;}
---MyDerivedClass1.cpp文件:

QX_寄存器CPP_QX_DLL2(MyDerivedClass1)
QX_持久化_CPP(MyDerivedClass1)
名称空间qx{
模板无效寄存器类(QxClass&t)
{
t、 数据(&MyDerivedClass1::description,“description”);
}}
---MyDerivedClass2.cpp文件:

QX_寄存器CPP_QX_DLL2(MyDerivedClass2)
QX_持久化_CPP(MyDerivedClass2)
名称空间qx{
模板无效寄存器类(QxClass&t)
{
t、 数据(&MyDerivedClass2::prop1,“prop1”);
t、 数据(&MyDerivedClass2::prop2,“prop2”);
}}
---MyContainer.cpp文件:

QX_注册表
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();
};
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;
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;
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;
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
QX_REGISTER_CPP_QX_DLL2(MyBaseClass)

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

MyBaseClass::~MyBaseClass() { ; }
QX_REGISTER_CPP_QX_DLL2(MyDerivedClass1)
QX_PERSISTABLE_CPP(MyDerivedClass1)

namespace qx {
template <> void register_class(QxClass<MyDerivedClass1> & t)
{
   t.data(& MyDerivedClass1::description, "description");
}}
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");
}}
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;
}
   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>>'