иерархическое сохранение в БД - как сделать?
То что я хочу - настолько для меня очевидно, что я не понимаю, почему не могу придумать незапутанную реализацию.
Что хочется иметь (на самом деле машинки - просто пример):
объекты классов
Cars Porshe Boxters ...
...
должны загружаться из базы по принципу:
данные специфичные для этого подкласса загружаются из таблицы подкласса,
а данные надкласса загружаются из таблицы надкласса и т.д.
таблицы в базе:
cars:
model color body...
boxters:
submodel roof_type ...
carreras:
submodel special_carrera_feauture ...
Вопрос в том, как сделать то что хочется без "острых углов".
templates вполне приемлимы.
Что хочется иметь (на самом деле машинки - просто пример):
объекты классов
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 вполне приемлимы.
