Revision 23337ecc
Von Christian Ehringfeld vor etwa 10 Jahren hinzugefügt
| src/entity.cpp | ||
|---|---|---|
|
}
|
||
|
|
||
|
Entity::~Entity() {
|
||
|
|
||
|
}
|
||
|
|
||
|
QList<ValidationRule> Entity::validationRules() const {
|
||
| ... | ... | |
|
return QString(this->metaObject()->className()).toLower();
|
||
|
}
|
||
|
|
||
|
QString Entity::getClassname() const {
|
||
|
return EntityHelper::getClassName(this);
|
||
|
}
|
||
|
|
||
|
const QHash<QString, Relation> Entity::getRelations() const {
|
||
|
return QHash<QString, Relation>();
|
||
|
}
|
||
| src/entity.h | ||
|---|---|---|
|
virtual ~Entity();
|
||
|
virtual QList<ValidationRule> validationRules() const;
|
||
|
virtual QString getTablename() const;
|
||
|
virtual QString getClassname() const;
|
||
|
virtual const QHash<QString, Relation> getRelations() const;
|
||
|
virtual const QStringList getTransientAttributes() const;
|
||
|
virtual const QStringList getBLOBColumns() const;
|
||
| src/entityhelper.cpp | ||
|---|---|---|
|
auto e = list.at(i);
|
||
|
if (e->getId() == remove->getId()) {
|
||
|
list.removeAt(i);
|
||
|
EntityHelper::setListProperty(entity, list, property);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
EntityHelper::setListProperty(entity, list, property);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void EntityHelper::clearEntityListProperty(const QSharedPointer<Entity> &entity,
|
||
|
const QMetaProperty &property) {
|
||
|
QVariant var = property.read(entity.data());
|
||
|
if (var.canConvert<QList<QVariant>>()) {
|
||
|
auto list = EntityInstanceFactory::castQVariantList(var);
|
||
|
list.clear();
|
||
|
EntityHelper::setListProperty(entity, list, property);
|
||
|
}
|
||
|
}
|
||
|
|
||
| src/entityhelper.h | ||
|---|---|---|
|
QSharedPointer<Entity> add, const QMetaProperty &property);
|
||
|
static void removeEntityFromListProperty(const QSharedPointer<Entity> &entity,
|
||
|
QSharedPointer<Entity> remove, const QMetaProperty &property);
|
||
|
static void clearEntityListProperty(const QSharedPointer<Entity> &entity, const QMetaProperty &property);
|
||
|
static void setListProperty(const QSharedPointer<Entity> &entity,
|
||
|
QList<QSharedPointer<Entity>> &list,
|
||
|
const QMetaProperty &property);
|
||
| src/entityinstancefactory.cpp | ||
|---|---|---|
|
Entity *EntityInstanceFactory::createInstance(const char *className,
|
||
|
const QHash<QString, QVariant> &attributes) {
|
||
|
Entity *e = EntityInstanceFactory::createInstance(className);
|
||
|
e = EntityInstanceFactory::setAttributes(e, attributes);
|
||
|
EntityInstanceFactory::setAttributes(e, attributes);
|
||
|
return e;
|
||
|
}
|
||
|
|
||
|
Entity *EntityInstanceFactory::setAttributes(Entity *&e,
|
||
|
void EntityInstanceFactory::setAttributes(Entity *&e,
|
||
|
const QHash<QString, QVariant> &attributes,
|
||
|
QHash<QString, QMetaProperty> metaprops) {
|
||
|
if (e) {
|
||
| ... | ... | |
|
++iterator;
|
||
|
}
|
||
|
}
|
||
|
return e;
|
||
|
}
|
||
|
|
||
|
Entity *EntityInstanceFactory::setAttributes(Entity *&e,
|
||
|
void EntityInstanceFactory::setAttributes(Entity *&e,
|
||
|
const QHash<QString, QVariant> &attributes) {
|
||
|
if (!attributes.isEmpty()) {
|
||
|
auto metaprops = EntityHelper::getMetaProperties(e);
|
||
|
return EntityInstanceFactory::setAttributes(e, attributes, metaprops);
|
||
|
} else {
|
||
|
return e;
|
||
|
EntityInstanceFactory::setAttributes(e, attributes, metaprops);
|
||
|
}
|
||
|
}
|
||
|
|
||
| ... | ... | |
|
|
||
|
QSharedPointer<Entity> EntityInstanceFactory::castQVariant(
|
||
|
QVariant &entity) {
|
||
|
return *reinterpret_cast<QSharedPointer<Entity>*>(entity.data());
|
||
|
if(!entity.isNull() && entity.data()) {
|
||
|
return *reinterpret_cast<QSharedPointer<Entity>*>(entity.data());
|
||
|
} else {
|
||
|
return QSharedPointer<Entity>();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
QStringList EntityInstanceFactory::getRegisteredClasses() {
|
||
| src/entityinstancefactory.h | ||
|---|---|---|
|
static Entity *createInstance(int metaTypeId);
|
||
|
static Entity *createInstance(const char *className,
|
||
|
const QHash<QString, QVariant> &attributes);
|
||
|
static Entity *setAttributes(Entity *&e,
|
||
|
static void setAttributes(Entity *&e,
|
||
|
const QHash<QString, QVariant> &attributes,
|
||
|
QHash<QString, QMetaProperty> metaprops);
|
||
|
static Entity *setAttributes(Entity *&e,
|
||
|
static void setAttributes(Entity *&e,
|
||
|
const QHash<QString, QVariant> &attributes);
|
||
|
static const QString extractEntityType(const QString &s);
|
||
|
static Entity *newSuperClassInstance(const Entity *e);
|
||
| src/entitymanager.cpp | ||
|---|---|---|
|
const bool ignoreHasChanged, const bool validate,
|
||
|
const bool relationsIgnoreHasChanged) {
|
||
|
bool merged = mergedObjects.contains(entity.data());
|
||
|
if (!merged && (ignoreHasChanged || this->hasChanged(entity))) {
|
||
|
if (entity && !merged && (ignoreHasChanged || this->hasChanged(entity))) {
|
||
|
if (entity->getProperty(entity->getPrimaryKey()).toLongLong() > -1) {
|
||
|
return this->mergeObject(entity, mergedObjects, persistRelations, validate,
|
||
|
relationsIgnoreHasChanged);
|
||
| ... | ... | |
|
QList<Entity *> &mergedObjects, bool withRelations, const bool validate,
|
||
|
const bool relationsIgnoreHasChanged) {
|
||
|
bool ok = true;
|
||
|
if (!mergedObjects.contains(entity.data())) {
|
||
|
if (entity && !mergedObjects.contains(entity.data())) {
|
||
|
mergedObjects.append(entity.data());
|
||
|
ok = false;
|
||
|
if (entity->getId() > -1 && (!validate || this->validate(entity))) {
|
||
| ... | ... | |
|
const bool checkDuplicate, const bool validate,
|
||
|
const bool relationsIgnoreHasChanged) {
|
||
|
bool rc = true;
|
||
|
if (!mergedObjects.contains(entity.data())) {
|
||
|
if (entity && !mergedObjects.contains(entity.data())) {
|
||
|
mergedObjects.append(entity.data());
|
||
|
rc = false;
|
||
|
if (this->checkTable(entity) && (!validate || this->validate(entity))
|
||
| ... | ... | |
|
break;
|
||
|
/**
|
||
|
* @todo error handling
|
||
|
*
|
||
|
*/
|
||
|
}
|
||
|
}
|
||
| ... | ... | |
|
}
|
||
|
|
||
|
void EntityManager::refresh(QSharedPointer<Entity> &entity) {
|
||
|
entity = this->findById(entity->getProperty(
|
||
|
entity->getPrimaryKey()).toLongLong(),
|
||
|
EntityHelper::getClassName(entity.data()));
|
||
|
if(entity) {
|
||
|
auto map = this->findByPk(entity->getId(), entity);
|
||
|
this->convert(map, entity, true);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
QList<QHash<QString, QVariant>> EntityManager::selectByQuery(Query &query) {
|
||
| ... | ... | |
|
QSharedPointer<Entity> r;
|
||
|
if (e && (refresh
|
||
|
|| !(r = this->cache.get(id, EntityHelper::getClassname(e.data()))))) {
|
||
|
e->setId(id);
|
||
|
auto map = this->findByPk(id, e);
|
||
|
r = this->convert(map, EntityHelper::getClassname(e.data()), refresh);
|
||
|
}
|
||
| ... | ... | |
|
while (iterator != relations.constEnd()) {
|
||
|
const Relation r = iterator.key();
|
||
|
auto var = iterator.value().read(entity.data());
|
||
|
if (var.data()) {
|
||
|
if (r.getType() == RelationType::MANY_TO_ONE) {
|
||
|
auto e = EntityInstanceFactory::castQVariant(var);
|
||
|
if (this->shouldBeSaved(e, r)) {
|
||
|
this->saveObject(e, mergedObjects, true, ignoreHasChanged);
|
||
|
auto fkProp = EntityHelper::mappedProperty(r, e);
|
||
|
if (fkProp.isValid()) {
|
||
|
EntityHelper::addEntityToListProperty(e, entity, fkProp);
|
||
|
}
|
||
|
}
|
||
|
} else if (r.getType() == RelationType::ONE_TO_ONE
|
||
|
&& r.getMappedBy().isEmpty()) {
|
||
|
auto e = EntityInstanceFactory::castQVariant(var);
|
||
|
if (r.getType() == RelationType::MANY_TO_ONE) {
|
||
|
auto e = EntityInstanceFactory::castQVariant(var);
|
||
|
if (this->shouldBeSaved(e, r)) {
|
||
|
this->saveObject(e, mergedObjects, true, ignoreHasChanged);
|
||
|
auto prop = EntityHelper::mappedProperty(r, e);
|
||
|
EntityHelper::setProperty(e, entity, prop);
|
||
|
auto fkProp = EntityHelper::mappedProperty(r, e);
|
||
|
if (e && fkProp.isValid()) {
|
||
|
EntityHelper::addEntityToListProperty(e, entity, fkProp);
|
||
|
}
|
||
|
}
|
||
|
} else if (r.getType() == RelationType::ONE_TO_ONE
|
||
|
&& r.getMappedBy().isEmpty()) {
|
||
|
auto e = EntityInstanceFactory::castQVariant(var);
|
||
|
this->saveObject(e, mergedObjects, true, ignoreHasChanged);
|
||
|
auto prop = EntityHelper::mappedProperty(r, e);
|
||
|
EntityHelper::setProperty(e, entity, prop);
|
||
|
}
|
||
|
++iterator;
|
||
|
}
|
||
| ... | ... | |
|
for (auto i = relations.constBegin(); i != relations.constEnd(); ++i) {
|
||
|
const Relation r = i.key();
|
||
|
auto var = i.value().read(entity.data());
|
||
|
if (!var.isNull() && var.data()) {
|
||
|
if (r.getType() == RelationType::MANY_TO_MANY) {
|
||
|
this->persistManyToMany(entity, r, var, mergedObjects, ignoreHasChanged,
|
||
|
newItem);
|
||
|
} else if (r.getType() == RelationType::ONE_TO_MANY) {
|
||
|
QList<QSharedPointer<Entity>> list = EntityInstanceFactory::castQVariantList(
|
||
|
var);
|
||
|
if (!list.isEmpty()) {
|
||
|
auto fkProp = EntityHelper::mappedProperty(r, list.at(0));
|
||
|
for (int var = 0; var < list.size(); ++var) {
|
||
|
auto e = list.at(var);
|
||
|
if (this->shouldBeSaved(e, r)) {
|
||
|
EntityHelper::setProperty(e, entity, fkProp);
|
||
|
this->saveObject(e, mergedObjects, true, ignoreHasChanged);
|
||
|
}
|
||
|
if (r.getType() == RelationType::MANY_TO_MANY) {
|
||
|
this->persistManyToMany(entity, r, var, mergedObjects, ignoreHasChanged,
|
||
|
newItem);
|
||
|
} else if (r.getType() == RelationType::ONE_TO_MANY) {
|
||
|
QList<QSharedPointer<Entity>> list = EntityInstanceFactory::castQVariantList(
|
||
|
var);
|
||
|
if (!list.isEmpty()) {
|
||
|
auto fkProp = EntityHelper::mappedProperty(r, list.at(0));
|
||
|
for (int var = 0; var < list.size(); ++var) {
|
||
|
auto e = list.at(var);
|
||
|
if (this->shouldBeSaved(e, r) && e) {
|
||
|
EntityHelper::setProperty(e, entity, fkProp);
|
||
|
this->saveObject(e, mergedObjects, true, ignoreHasChanged);
|
||
|
}
|
||
|
}
|
||
|
} else if (r.getType() == RelationType::ONE_TO_ONE
|
||
|
&& !r.getMappedBy().isEmpty()) {
|
||
|
auto e = EntityInstanceFactory::castQVariant(var);
|
||
|
if(e) {
|
||
|
auto fkProp = EntityHelper::mappedProperty(r, e);
|
||
|
EntityHelper::setProperty(e, entity, fkProp);
|
||
|
this->saveObject(e, mergedObjects, true, ignoreHasChanged);
|
||
|
}
|
||
|
}
|
||
|
} else if (r.getType() == RelationType::ONE_TO_ONE
|
||
|
&& !r.getMappedBy().isEmpty()) {
|
||
|
auto e = EntityInstanceFactory::castQVariant(var);
|
||
|
if(e) {
|
||
|
auto fkProp = EntityHelper::mappedProperty(r, e);
|
||
|
EntityHelper::setProperty(e, entity, fkProp);
|
||
|
this->saveObject(e, mergedObjects, true, ignoreHasChanged);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
| ... | ... | |
|
|
||
|
bool EntityManager::shouldBeSaved(QSharedPointer<Entity> &entity,
|
||
|
const Relation &r) {
|
||
|
return entity && (r.getCascadeType().contains(CascadeType::ALL)
|
||
|
|| (entity->getProperty(entity->getPrimaryKey()) > -1
|
||
|
&& r.getCascadeType().contains(CascadeType::MERGE))
|
||
|
|| (entity->getProperty(entity->getPrimaryKey()) <= -1
|
||
|
&& r.getCascadeType().contains(CascadeType::PERSIST)));
|
||
|
return r.getCascadeType().contains(CascadeType::ALL)
|
||
|
|| ((!entity || entity->getProperty(entity->getPrimaryKey()) > -1)
|
||
|
&& r.getCascadeType().contains(CascadeType::MERGE))
|
||
|
|| ((!entity || entity->getProperty(entity->getPrimaryKey()) <= -1)
|
||
|
&& r.getCascadeType().contains(CascadeType::PERSIST));
|
||
|
}
|
||
|
|
||
|
void EntityManager::removeRelations(const QSharedPointer<Entity> &entity) {
|
||
| ... | ... | |
|
const Relation &r, QVariant &property, QList<Entity *> &mergedObjects,
|
||
|
const bool ignoreHasChanged, const bool newItem) {
|
||
|
auto list = property.value<QList<QVariant>>();
|
||
|
if (!list.isEmpty() && list.at(0).data()) {
|
||
|
auto var = list.at(0);
|
||
|
auto ptr = EntityInstanceFactory::castQVariant(var);
|
||
|
auto builder = this->schema->getQueryBuilder();
|
||
|
QString tblName = builder->generateManyToManyTableName(entity, ptr, r);
|
||
|
if (this->schema->containsTable(tblName)) {
|
||
|
bool ok = newItem;
|
||
|
QSqlQuery q;
|
||
|
if (!newItem) {
|
||
|
q = builder->manyToManyDelete(
|
||
|
tblName, builder->generateManyToManyColumnName(entity),
|
||
|
entity->getProperty(entity->getPrimaryKey()).toLongLong());
|
||
|
ok = this->db->exec(q);
|
||
|
} else {
|
||
|
q = builder->getQuery();
|
||
|
}
|
||
|
if (ok) {
|
||
|
auto nList = EntityInstanceFactory::castQVariantList(property);
|
||
|
this->persistMappedByRelation(nList, q, entity, ptr, r, tblName, mergedObjects);
|
||
|
}
|
||
|
auto ptr = QSharedPointer<Entity>(EntityInstanceFactory::createInstance(
|
||
|
EntityInstanceFactory::extractEntityType(QString(property.typeName()))));
|
||
|
auto builder = this->schema->getQueryBuilder();
|
||
|
QString tblName = builder->generateManyToManyTableName(entity, ptr, r);
|
||
|
if (this->schema->containsTable(tblName)) {
|
||
|
bool ok = newItem;
|
||
|
QSqlQuery q;
|
||
|
if (!newItem) {
|
||
|
/**
|
||
|
* @todo diff and remove entity from relational object when association is deleted
|
||
|
*/
|
||
|
q = builder->manyToManyDelete(
|
||
|
tblName, builder->generateManyToManyColumnName(entity),
|
||
|
entity->getProperty(entity->getPrimaryKey()).toLongLong());
|
||
|
ok = this->db->exec(q);
|
||
|
} else {
|
||
|
this->missingManyToManyTable(tblName, entity, r);
|
||
|
q = builder->getQuery();
|
||
|
}
|
||
|
if (ok && !list.isEmpty() && list.at(0).data()) {
|
||
|
auto nList = EntityInstanceFactory::castQVariantList(property);
|
||
|
this->persistMappedByRelation(nList, q, entity, ptr, r, tblName, mergedObjects);
|
||
|
}
|
||
|
} else {
|
||
|
this->missingManyToManyTable(tblName, entity, r);
|
||
|
}
|
||
|
}
|
||
|
|
||
| ... | ... | |
|
(EntityInstanceFactory::createInstance(EntityInstanceFactory::extractEntityType(
|
||
|
QString(property.typeName()))));
|
||
|
auto builder = this->schema->getQueryBuilder();
|
||
|
EntityHelper::clearEntityListProperty(entity, property);
|
||
|
if (secEntityPtr) {
|
||
|
QString tblName = builder->generateManyToManyTableName(entity, secEntityPtr,
|
||
|
relation);
|
||
| ... | ... | |
|
return this->schema->getQueryBuilder()->createTable(e, createRelationTables);
|
||
|
}
|
||
|
|
||
|
bool EntityManager::removeTable(QString className) {
|
||
|
return this->executeQuery(this->schema->getQueryBuilder()->dropTable(className));
|
||
|
}
|
||
|
|
||
|
quint8 EntityManager::count(const QSharedPointer<Entity> &entity, bool ignoreID,
|
||
|
bool followInheritance) {
|
||
|
Query q = Query();
|
||
| ... | ... | |
|
return ptr;
|
||
|
}
|
||
|
|
||
|
void EntityManager::convert(const QHash<QString, QVariant> &map,
|
||
|
QSharedPointer<Entity> &entity, const bool refresh, const bool resolveRelations) {
|
||
|
this->cache.insert(entity);
|
||
|
auto data = entity.data();
|
||
|
EntityInstanceFactory::setAttributes(data, map);
|
||
|
if (resolveRelations) {
|
||
|
this->resolveRelations(entity, map, refresh);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
QList<QSharedPointer<Entity>> EntityManager::convert(
|
||
|
QList<QHash<QString, QVariant>> maps,
|
||
|
const char *classname, const bool refresh, const bool resolveRelations) {
|
||
| src/entitymanager.h | ||
|---|---|---|
|
bool createTable(const QSharedPointer<Entity> &entity,
|
||
|
bool createRelationTables = true);
|
||
|
bool createTable(QString className, bool createRelationTables = true);
|
||
|
bool removeTable(QString className);
|
||
|
quint8 count(const QSharedPointer<Entity> &entity, bool ignoreID = true,
|
||
|
bool followInheritance = false);
|
||
|
quint8 count(const QString &tableName);
|
||
| ... | ... | |
|
QSharedPointer<Entity> convert(const QHash<QString, QVariant> &map,
|
||
|
const char *classname, const bool refresh = false,
|
||
|
const bool resolveRelations = true);
|
||
|
void convert(const QHash<QString, QVariant> &map, QSharedPointer<Entity> &entity, const bool refresh = false,
|
||
|
const bool resolveRelations = true);
|
||
|
QList<QSharedPointer<Entity>> convert(QList<QHash<QString, QVariant>> maps,
|
||
|
const char *classname, const bool refresh = false,
|
||
|
const bool resolveRelations = true);
|
||
Auch abrufbar als: Unified diff
bugfixxes