Image

Imagecoastwalker wrote in Imageru_cpp

иерархическое сохранение в БД - как сделать?

То что я хочу - настолько для меня очевидно, что я не понимаю, почему не могу придумать незапутанную реализацию.

Что хочется иметь (на самом деле машинки - просто пример):
объекты классов
Cars Porshe Boxters ...
...
должны загружаться из базы по принципу:
данные специфичные для этого подкласса загружаются из таблицы подкласса,
а данные надкласса загружаются из таблицы надкласса и т.д.

таблицы в базе:
cars:
model color body...

boxters:
submodel roof_type ...

carreras:
submodel special_carrera_feauture ...



DbElement()
{
public:
virtual String GetTableName() = 0;

bool ExistsInDb()
{
GetTableName(); // Проблема в коде ниже.
// должна быть вызвана GetTableName
// того класса, в котором вызвана
// функция ExistsInDb().
// но будет вызвана
// функция его наследника.
...
return true;
};

int AddToDb()
{
if( ExistsInDb() ) // Проблема в коде ниже,
return 1; // ExistsInDb будет вызвана для
// самого последнего наследника,
// а не для класса, в котором мы хотим
// что бы она была вызвана.
return 0;
}

void LoadFromDb()
{
Query query = GetFromDb(); // Та же проблема возникнет
LoadFromQuery( Query ); // при вызове этой функции.
}
private:
Query int GetFromDb() = 0;
virtual void LoadFromQuery( Query ) = 0;
};

class Car : public DbElement()
{
public:
virtual String GetTableName()
{
return "cars";
}

virtual bool ExistsInDb()
{
if ( ExistsInDb() ) // Тут проблема.
return true; // Должна быть вызывана
// Car::ExistsInDb и в ней
// Car::GetTableName.


return false;
}


private:
virtual Query GetFromDb()
{
Query query;
...
return query;
}

virtual void LoadFromQuery( Query q )
{
...
}
};




class Boxter : public Car
{
public:
virtual String GetTableName()
{
return "boxters";
}

virtual bool ExistsInDb()
{
if ( ExistsInDb() ) // Должна быть вызывана
return true; // Boxter::ExistsInDb и в ней
// Boxter::GetTableName.


return false;
}

private:
virtual Query GetFromDb()
{
Car::LoadFromDb(); // Ожидается что все функции
// внутри будут
// вызваны для Car.
Query query;
...
return query;
}

virtual void LoadFromQuery( Query q )
{
...
}
}


Теперь имеем это всё, и хотим делать так:


// Записывать машины в базу:
void Shop::AddNewCar( Car *car )
{
car->AddToDb();
}

// Загружать машины из базы:
void Shop::LoadCarInfo( Car *car )
{
car->LoadFromDatabase();
}



Вопрос в том, как сделать то что хочется без "острых углов".
templates вполне приемлимы.