Revision d2bebf1b
Von Christian Ehringfeld vor etwa 9 Jahren hinzugefügt
src/entitymanager.cpp | ||
---|---|---|
|
||
bool EntityManager::saveObject(QSharedPointer<Entity> &entity,
|
||
QList<Entity *> &mergedObjects, const bool persistRelations,
|
||
const bool ignoreHasChanged, const bool validate) {
|
||
const bool ignoreHasChanged, const bool validate,
|
||
const bool relationsIgnoreHasChanged) {
|
||
bool merged = mergedObjects.contains(entity.data());
|
||
if (ignoreHasChanged || (!ignoreHasChanged && !merged
|
||
&& this->hasChanged(entity))) {
|
||
if (!merged && (ignoreHasChanged || this->hasChanged(entity))) {
|
||
if (entity->getProperty(entity->getPrimaryKey()).toLongLong() > -1) {
|
||
return this->mergeObject(entity, mergedObjects, persistRelations, validate);
|
||
return this->mergeObject(entity, mergedObjects, persistRelations, validate,
|
||
relationsIgnoreHasChanged);
|
||
} else {
|
||
return this->createObject(entity, mergedObjects, persistRelations, false,
|
||
validate);
|
||
validate, relationsIgnoreHasChanged);
|
||
}
|
||
}
|
||
return merged ? true : false;
|
||
}
|
||
|
||
bool EntityManager::mergeObject(QSharedPointer<Entity> &entity,
|
||
QList<Entity *> &mergedObjects, bool withRelations, const bool validate) {
|
||
QList<Entity *> &mergedObjects, bool withRelations, const bool validate,
|
||
const bool relationsIgnoreHasChanged) {
|
||
bool ok = true;
|
||
if (!mergedObjects.contains(entity.data())) {
|
||
mergedObjects.append(entity.data());
|
||
ok = false;
|
||
if (entity->getId() > -1 && ((validate && this->validate(entity))
|
||
|| !validate)) {
|
||
if (entity->getId() > -1 && (!validate || this->validate(entity))) {
|
||
if (withRelations) {
|
||
this->savePrePersistedRelations(entity, mergedObjects);
|
||
this->savePrePersistedRelations(entity, mergedObjects,
|
||
relationsIgnoreHasChanged);
|
||
}
|
||
this->db->startTransaction();
|
||
QList<QSqlQuery> q = this->schema->getQueryBuilder()->merge(
|
||
... | ... | |
this->db->rollbackTransaction();
|
||
ok = false;
|
||
} else if (ok && withRelations) {
|
||
this->savePostPersistedRelations(entity, mergedObjects);
|
||
this->savePostPersistedRelations(entity, mergedObjects,
|
||
relationsIgnoreHasChanged);
|
||
}
|
||
}
|
||
}
|
||
... | ... | |
|
||
bool EntityManager::createObject(QSharedPointer<Entity> &entity,
|
||
QList<Entity *> &mergedObjects, const bool persistRelations,
|
||
const bool checkDuplicate, const bool validate) {
|
||
const bool checkDuplicate, const bool validate,
|
||
const bool relationsIgnoreHasChanged) {
|
||
bool rc = true;
|
||
if (!mergedObjects.contains(entity.data())) {
|
||
mergedObjects.append(entity.data());
|
||
rc = false;
|
||
if (this->checkTable(entity) && ((validate && this->validate(entity))
|
||
|| !validate) && !(checkDuplicate && this->count(entity) > 0)) {
|
||
if (this->checkTable(entity) && (!validate || this->validate(entity))
|
||
&& !(checkDuplicate && this->count(entity) > 0)) {
|
||
if (persistRelations) {
|
||
this->savePrePersistedRelations(entity, mergedObjects);
|
||
this->savePrePersistedRelations(entity, mergedObjects,
|
||
relationsIgnoreHasChanged);
|
||
}
|
||
this->db->startTransaction();
|
||
QList<QSqlQuery> q = this->schema->getQueryBuilder()->create(
|
||
... | ... | |
} else {
|
||
this->cache.insert(entity);
|
||
if (persistRelations) {
|
||
this->savePostPersistedRelations(entity, mergedObjects);
|
||
this->savePostPersistedRelations(entity, mergedObjects,
|
||
relationsIgnoreHasChanged);
|
||
}
|
||
rc = true;
|
||
}
|
||
... | ... | |
|
||
|
||
bool EntityManager::merge(QSharedPointer<Entity> &entity, bool withRelations,
|
||
const bool validate) {
|
||
const bool validate, const bool relationsIgnoreHasChanged) {
|
||
auto merged = QList<Entity *>();
|
||
return this->mergeObject(entity, merged, withRelations, validate);
|
||
return this->mergeObject(entity, merged, withRelations, validate,
|
||
relationsIgnoreHasChanged);
|
||
}
|
||
|
||
/**
|
||
... | ... | |
* @return
|
||
*/
|
||
bool EntityManager::create(QSharedPointer<Entity> &entity,
|
||
const bool persistRelations, const bool checkDuplicate, const bool validate) {
|
||
const bool persistRelations, const bool checkDuplicate, const bool validate,
|
||
const bool relationsIgnoreHasChanged) {
|
||
auto merged = QList<Entity *>();
|
||
return this->createObject(entity, merged, persistRelations,
|
||
checkDuplicate, validate);
|
||
checkDuplicate, validate, relationsIgnoreHasChanged);
|
||
}
|
||
/**
|
||
* @brief EntityManager::save
|
||
... | ... | |
* @return bool
|
||
*/
|
||
bool EntityManager::save(QSharedPointer<Entity> &entity,
|
||
const bool persistRelations, const bool ignoreHasChanged, const bool validate) {
|
||
const bool persistRelations, const bool ignoreHasChanged, const bool validate,
|
||
const bool relationsIgnoreHasChanged) {
|
||
auto merged = QList<Entity *>();
|
||
return this->saveObject(entity, merged, persistRelations,
|
||
ignoreHasChanged, validate);
|
||
ignoreHasChanged, validate, relationsIgnoreHasChanged);
|
||
}
|
||
|
||
EntityManager::EntityManager(QSqlDatabase database,
|
||
... | ... | |
return rc;
|
||
}
|
||
|
||
/**
|
||
* @brief EntityManager::validate
|
||
* This validates an entity. Its uses the validationRules() method of the specified entity.
|
||
* If there are validation errors, this method will set these errors in the entity object.
|
||
* You can check them with entity->hasErrors(), entity->getErrors() or entity->getErrorsAsString()
|
||
* @param entity
|
||
* @return true if it has no validation errors, false if it has errors
|
||
*/
|
||
bool EntityManager::validate(QSharedPointer<Entity> &entity) {
|
||
QList<ValidationRule> rules = entity->validationRules();
|
||
QList<ErrorMsg> list = QList<ErrorMsg>();
|
||
... | ... | |
}
|
||
}
|
||
|
||
/**
|
||
* @brief EntityManager::savePrePersistedRelations
|
||
* @param entity
|
||
* @param mergedObjects
|
||
* @throw can throw in debug mode a QString exception when the type of any Relation is wrong @see EntityManager::checkRelation
|
||
*/
|
||
void EntityManager::savePrePersistedRelations(const QSharedPointer<Entity>
|
||
&entity, QList<Entity *> &mergedObjects) {
|
||
&entity, QList<Entity *> &mergedObjects, bool ignoreHasChanged) {
|
||
auto relations = EntityHelper::getRelationProperties(entity.data());
|
||
auto iterator = relations.constBegin();
|
||
while (iterator != relations.constEnd()) {
|
||
... | ... | |
if (r.getType() == RelationType::MANY_TO_ONE) {
|
||
auto e = EntityInstanceFactory::castQVariant(var);
|
||
if (this->shouldBeSaved(e, r)) {
|
||
this->saveObject(e, mergedObjects);
|
||
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);
|
||
this->saveObject(e, mergedObjects);
|
||
this->saveObject(e, mergedObjects, true, ignoreHasChanged);
|
||
auto prop = EntityHelper::mappedProperty(r, e);
|
||
if (prop.isValid()) {
|
||
EntityHelper::setProperty(e, entity, prop);
|
||
... | ... | |
}
|
||
}
|
||
|
||
/**
|
||
* @brief EntityManager::savePostPersistedRelations
|
||
* @param entity
|
||
* @param mergedObjects
|
||
* @throw can throw in debug mode a QString exception when the type of any Relation is wrong @see EntityManager::checkRelation
|
||
*/
|
||
void EntityManager::savePostPersistedRelations(const QSharedPointer<Entity>
|
||
&entity, QList<Entity *> &mergedObjects) {
|
||
&entity, QList<Entity *> &mergedObjects, bool ignoreHasChanged) {
|
||
auto relations = EntityHelper::getRelationProperties(entity.data());
|
||
auto iterator = relations.constBegin();
|
||
while (iterator != relations.constEnd()) {
|
||
... | ... | |
this->checkRelation(var, r);
|
||
#endif
|
||
if (r.getType() == RelationType::MANY_TO_MANY) {
|
||
this->persistManyToMany(entity, r, var, mergedObjects);
|
||
this->persistManyToMany(entity, r, var, mergedObjects, ignoreHasChanged);
|
||
} else if (r.getType() == RelationType::ONE_TO_MANY) {
|
||
QList<QSharedPointer<Entity>> list = EntityInstanceFactory::castQVariantList(
|
||
var);
|
||
... | ... | |
for (int var = 0; var < list.size(); ++var) {
|
||
auto e = list.at(var);
|
||
if (this->shouldBeSaved(e, r)) {
|
||
this->saveObject(e, mergedObjects);
|
||
this->saveObject(e, mergedObjects, true, ignoreHasChanged);
|
||
if (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);
|
||
this->saveObject(e, mergedObjects, true, ignoreHasChanged);
|
||
auto fkProp = EntityHelper::mappedProperty(r, e);
|
||
if (fkProp.isValid()) {
|
||
EntityHelper::addEntityToListProperty(e, entity, fkProp);
|
||
... | ... | |
return propertyIsValid;
|
||
}
|
||
|
||
/**
|
||
* @brief EntityManager::generateObjectName
|
||
* Generates a object name with this scheme: em[anyNumber]
|
||
* @return
|
||
*/
|
||
QString EntityManager::generateObjectName() {
|
||
int i = 0;
|
||
QString name = "em[";
|
||
... | ... | |
}
|
||
|
||
void EntityManager::persistManyToMany(const QSharedPointer<Entity> &entity,
|
||
const Relation &r, QVariant &property, QList<Entity *> &mergedObjects) {
|
||
const Relation &r, QVariant &property, QList<Entity *> &mergedObjects,
|
||
const bool ignoreHasChanged) {
|
||
auto list = property.value<QList<QVariant>>();
|
||
if (!list.isEmpty() && !(list.at(0).isNull())) {
|
||
auto var = list.at(0);
|
||
... | ... | |
qWarning() << "Entity " << EntityHelper::getClassName(e.data()) <<
|
||
" is affected";
|
||
qWarning() << "Relation of property: " << r.getPropertyName();
|
||
/**
|
||
@todo wait for Qt 5.5.1
|
||
@see https://codereview.qt-project.org/#/c/122232/
|
||
*/
|
||
//qDebug() << "RelationType:" << r.getType() << " MappedBy:" << r.getMappedBy();
|
||
}
|
||
|
||
... | ... | |
return this->convert(maps, EntityHelper::getClassname(entity.data()));
|
||
}
|
||
|
||
/**
|
||
* @todo should be an insert statement with many values
|
||
* @brief EntityManager::create
|
||
* @param entities
|
||
* @return
|
||
*/
|
||
bool EntityManager::create(QList<QSharedPointer<Entity> > entities,
|
||
const bool persistRelations, const bool validate) {
|
||
const bool persistRelations, const bool validate,
|
||
const bool relationsIgnoreHasChanged) {
|
||
bool ok = true;
|
||
foreach (QSharedPointer<Entity> ent, entities) {
|
||
ok = this->create(ent, persistRelations, validate);
|
||
ok = this->create(ent, persistRelations, validate, relationsIgnoreHasChanged);
|
||
if (!ok) {
|
||
break;
|
||
}
|
src/entitymanager.h | ||
---|---|---|
QSharedPointer<Entity> &entity,
|
||
bool ignoreID = false);
|
||
qint64 findId(QSharedPointer<Entity> &entity);
|
||
/**
|
||
* @todo should be an insert statement with many values
|
||
* @brief EntityManager::create
|
||
* @param entities
|
||
* @return
|
||
*/
|
||
bool create(QList<QSharedPointer<Entity>> entities,
|
||
const bool persistRelations = true, const bool validate = true);
|
||
const bool persistRelations = true, const bool validate = true, const bool relationsIgnoreHasChanged = false);
|
||
bool create(QSharedPointer<Entity> &entity, const bool persistRelations = true,
|
||
const bool checkDuplicate = false, const bool validate = true);
|
||
const bool checkDuplicate = false, const bool validate = true, const bool relationsIgnoreHasChanged = false) ;
|
||
bool save(QSharedPointer<Entity> &entity, const bool persistRelations = true,
|
||
const bool ignoreHasChanged = true, const bool validate = true);
|
||
const bool ignoreHasChanged = false, const bool validate = true, const bool relationsIgnoreHasChanged = false);
|
||
bool merge(QSharedPointer<Entity> &entity, bool withRelations = true,
|
||
const bool validate = true);
|
||
const bool validate = true, const bool relationsIgnoreHasChanged = false);
|
||
bool remove(QSharedPointer<Entity> &entity);
|
||
bool removeAll(QString tblname);
|
||
bool createTable(const QSharedPointer<Entity> &entity,
|
||
... | ... | |
QList<QHash<QString, QVariant> > selectByQuery(Query &query);
|
||
QList<QHash<QString, QVariant> > selectBySql(const QString &sql);
|
||
qint8 count(Query &query);
|
||
/**
|
||
* @brief EntityManager::validate
|
||
* This validates an entity. Its uses the validationRules() method of the specified entity.
|
||
* If there are validation errors, this method will set these errors in the entity object.
|
||
* You can check them with entity->hasErrors(), entity->getErrors() or entity->getErrorsAsString()
|
||
* @param entity
|
||
* @return true if it has no validation errors, false if it has errors
|
||
*/
|
||
bool validate(QSharedPointer<Entity> &entity);
|
||
/**
|
||
* @brief hasChanged
|
||
* @param entity
|
||
* @todo check manyToMany relations
|
||
* @return
|
||
*/
|
||
bool hasChanged(QSharedPointer<Entity> &entity);
|
||
|
||
|
||
public:
|
||
EntityManager(QSqlDatabase database, bool logQueries = false);
|
||
EntityManager(const QString &databaseType, QString databasename = "" ,
|
||
... | ... | |
}
|
||
|
||
protected:
|
||
bool saveObject(QSharedPointer<Entity> &entity, QList<Entity*> &mergedObjects, const bool persistRelations=true,
|
||
const bool ignoreHasChanged=true, const bool validate=true);
|
||
bool mergeObject(QSharedPointer<Entity> &entity, QList<Entity*> &mergedObjects, bool withRelations,
|
||
const bool validate);
|
||
bool createObject(QSharedPointer<Entity> &entity, QList<Entity*> &mergedObjects,const bool persistRelations,
|
||
const bool checkDuplicate, const bool validate);
|
||
bool saveObject(QSharedPointer<Entity> &entity, QList<Entity *> &mergedObjects,
|
||
const bool persistRelations = true,
|
||
const bool ignoreHasChanged = false, const bool validate = true,
|
||
const bool relationsIgnoreHasChanged = false);
|
||
bool mergeObject(QSharedPointer<Entity> &entity, QList<Entity *> &mergedObjects,
|
||
bool withRelations,
|
||
const bool validate, const bool relationsIgnoreHasChanged = false);
|
||
bool createObject(QSharedPointer<Entity> &entity,
|
||
QList<Entity *> &mergedObjects, const bool persistRelations,
|
||
const bool checkDuplicate, const bool validate,
|
||
const bool relationsIgnoreHasChanged = false);
|
||
template<class T> QList<QSharedPointer<T>> convertList(const
|
||
QList<QSharedPointer<Entity>> &list) {
|
||
QList<QSharedPointer<T>> newList = QList<QSharedPointer<T>>();
|
||
... | ... | |
const QMetaProperty &property, const bool refresh = false,
|
||
const QVariant &id = "");
|
||
void persistManyToMany(const QSharedPointer<Entity> &entity, const Relation &r,
|
||
QVariant &property, QList<Entity*> &mergedObjects);
|
||
QVariant &property, QList<Entity *> &mergedObjects,
|
||
const bool ignoreHasChanged = false);
|
||
QList<QHash<QString, QVariant> > findAllByAttributes(const
|
||
QSharedPointer<Entity> &entity,
|
||
bool ignoreID = false);
|
||
... | ... | |
bool ignoreID = false);
|
||
QSharedPointer<Entity> findById(const qint64 &id, QSharedPointer<Entity> &e,
|
||
const bool refresh = false);
|
||
void savePrePersistedRelations(const QSharedPointer<Entity> &entity, QList<Entity*> &mergedObjects);
|
||
void savePostPersistedRelations(const QSharedPointer<Entity> &entity, QList<Entity*> &mergedObjects);
|
||
/**
|
||
* @brief EntityManager::savePrePersistedRelations
|
||
* @param entity
|
||
* @param mergedObjects
|
||
* @throw can throw in debug mode a QString exception when the type of any Relation is wrong @see EntityManager::checkRelation
|
||
*/
|
||
void savePrePersistedRelations(const QSharedPointer<Entity> &entity,
|
||
QList<Entity *> &mergedObjects, bool ignoreHasChanged = false);
|
||
/**
|
||
* @brief EntityManager::savePostPersistedRelations
|
||
* @param entity
|
||
* @param mergedObjects
|
||
* @throw can throw in debug mode a QString exception when the type of any Relation is wrong @see EntityManager::checkRelation
|
||
*/
|
||
void savePostPersistedRelations(const QSharedPointer<Entity> &entity,
|
||
QList<Entity *> &mergedObjects, bool ignoreHasChanged = false);
|
||
|
||
QList<QSharedPointer<Entity>> saveRelationEntities(const
|
||
QList<QSharedPointer<Entity>> &list, const Relation &r, QList<Entity*> &mergedObjects);
|
||
QList<QSharedPointer<Entity>> &list, const Relation &r,
|
||
QList<Entity *> &mergedObjects);
|
||
/**
|
||
* @brief EntityManager::persistManyToMany
|
||
* @param entity
|
||
* @param r
|
||
* @param property
|
||
* @param mergedObjects
|
||
* @todo compare old values with new values if nothing has changed don't persist them
|
||
*/
|
||
void persistMappedByRelation(const QList<QSharedPointer<Entity>> &list,
|
||
QSqlQuery &q, const QSharedPointer<Entity> &entity,
|
||
const QSharedPointer<Entity> &ptr, const Relation &r,
|
||
const QString &tblName, QList<Entity*> &mergedObjects);
|
||
const QString &tblName, QList<Entity *> &mergedObjects);
|
||
bool shouldBeSaved(QSharedPointer<Entity> &entity , const Relation &r);
|
||
void removeRelations(const QSharedPointer<Entity> &entity);
|
||
void removeEntityList(QVariant &var);
|
||
... | ... | |
QList<QSharedPointer<Entity>> convert(QList<QHash<QString, QVariant> > maps,
|
||
const char *classname, const bool refresh = false,
|
||
const bool resolveRelations = true);
|
||
/**
|
||
@todo wait for Qt 5.5.1
|
||
@see https://codereview.qt-project.org/#/c/122232/
|
||
*/
|
||
void missingManyToManyTable(const QString &tblName,
|
||
const QSharedPointer<Entity> &e, const Relation &r);
|
||
bool isRelationPropertyValid(const QMetaProperty &prop, const Relation &r,
|
||
const QSharedPointer<Entity> &e, const QSharedPointer<Entity> &relatedEntity);
|
||
/**
|
||
* @brief EntityManager::generateObjectName
|
||
* Generates a object name with this scheme: em[anyNumber]
|
||
* @return
|
||
*/
|
||
QString generateObjectName();
|
||
void appendToInstanceList();
|
||
|
Auch abrufbar als: Unified diff
improvements