diff --git a/include/sqlQueryExecutor.h b/include/sqlQueryExecutor.h index 5a952e8..2ee9942 100644 --- a/include/sqlQueryExecutor.h +++ b/include/sqlQueryExecutor.h @@ -13,7 +13,7 @@ class SqlQueryExecutor : public QObject public: static SqlQueryExecutor& instance(); //基础SQL语句执行接口 - QSqlQuery executeSQL(const QString& strConnectionName, const QString& strSQL, const QVariantHash& params = {}); + QSqlQuery executeSQL(const QString& strConnectionName, const QString& strSQL, const QVariantHash& params = {}, bool useTranscation = false); //基于具体业务的查询接口-对外调用 const QVector getModels(const QString&); const QVector getAttributeGroup(const QString&); diff --git a/source/sqlQueryExecutor.cpp b/source/sqlQueryExecutor.cpp index 6d9d7b8..f7cc543 100644 --- a/source/sqlQueryExecutor.cpp +++ b/source/sqlQueryExecutor.cpp @@ -16,28 +16,67 @@ SqlQueryExecutor::~SqlQueryExecutor() {} //基础SQL语句执行接口 -QSqlQuery SqlQueryExecutor::executeSQL(const QString& strConnectionName, const QString& strSQL, const QVariantHash& params) +QSqlQuery SqlQueryExecutor::executeSQL(const QString& strConnectionName, const QString& strSQL, const QVariantHash& params, bool useTranscation) { QSqlDatabase db = QSqlDatabase::database(strConnectionName); if(!db.isOpen()) { - LOG_ERROR("DB", QString("Database not open. connectionName: %1. error:").arg(strConnectionName)); + LOG_ERROR("DB", QString("Database not open. connectionName: %1").arg(strConnectionName)); throw DatabaseException(db.lastError()); } + //事务 + bool transactionStarted = false; + if(useTranscation) + { + if(!db.transaction()) + { + LOG_ERROR("DB", QString("Start transaction failed. connectionName: %1. error: %2").arg(strConnectionName, db.lastError().databaseText())); + throw DatabaseException(db.lastError()); + } + transactionStarted = true; + } + QSqlQuery sqlQuery(db); - sqlQuery.prepare(strSQL); - //绑定参数 - for(auto it = params.constBegin(); it != params.constEnd(); it++) + try { - sqlQuery.bindValue(it.key(), it.value()); + if(!sqlQuery.prepare(strSQL)) + { + LOG_ERROR("SQL", QString("SQL '%1' prepare fialed. error: %2").arg(strSQL, sqlQuery.lastError().databaseText())); + throw DatabaseException(db.lastError()); + } + //绑定参数 + for(auto it = params.constBegin(); it != params.constEnd(); it++) + { + sqlQuery.bindValue(it.key(), it.value()); + } + if (!sqlQuery.exec()) + { + LOG_ERROR("SQL", QString("SQL '%1' execute error: %2").arg(strSQL, sqlQuery.lastError().databaseText())); + throw DatabaseException(sqlQuery.lastError()); + } + // 提交事务(如果已开启) + if(transactionStarted && !db.commit()) + { + throw DatabaseException(db.lastError()); + LOG_ERROR("DB", QString("Commit transaction failed. connectionName: %1. error: %2").arg(strConnectionName, db.lastError().databaseText())); + } } - if (!sqlQuery.exec(strSQL)) + catch (const DatabaseException& e) { - LOG_ERROR("SQL", QString("SQL '%1' execute error: %2").arg(strSQL).arg(sqlQuery.lastError().databaseText())); - throw DatabaseException(sqlQuery.lastError()); + // 错误处理:回滚事务(如果已开启) + if(transactionStarted) + { + if(!db.rollback()) // 回滚失败时记录警告 + { + LOG_ERROR("DB", QString("Rollback failed. connectionName: %1. error: %2").arg(strConnectionName, db.lastError().databaseText())); + } + } + + throw; // 重新抛出异常 } + return sqlQuery; } @@ -68,7 +107,7 @@ const QVector SqlQueryExecutor::getModels(const QString& strConnectionNam QVector SqlQueryExecutor::getModelGroups(const QString& strConnectionName, int modelID) { QVector groups; - QString strSQL = "SELECT attribute_group_id FROM basic.mapping_model_group WHERE model_type_id = " + QString::number(modelID); + QString strSQL = "SELECT attribute_group_id FROM basic.model_group WHERE model_type_id = " + QString::number(modelID); try { QSqlQuery query = executeSQL(strConnectionName, strSQL); @@ -89,18 +128,17 @@ bool SqlQueryExecutor::addModel(const QString& connectionName, Model& model) { int modelID = -1; //先向model_type中插入一条记录 - /*QString strSQL = "INSERT INTO basic.model_type (model_type, model_name, remark) VALUES " + QString strSQL = "INSERT INTO basic.model_type (model_type, model_name, remark) VALUES " "(:type, :name, :remark)"; QVariantHash params; params.insert(":type", model.type); params.insert(":name", model.name); - params.insert(":remark", model.remark);*/ - //因为不同数据库的占位符不同,所以不采用上面注释掉的这种占位符方式 - QString strSQL = "INSERT INTO basic.model_type (model_type, model_name, remark) VALUES (\'" + - model.type + "\',\'" + model.name + + "\',\'" + model.remark +"\')"; + params.insert(":remark", model.remark); + /*QString strSQL = "INSERT INTO basic.model_type (model_type, model_name, remark) VALUES (\'" + + model.type + "\',\'" + model.name + + "\',\'" + model.remark +"\')";*/ try { - QSqlQuery query = executeSQL(connectionName, strSQL); + QSqlQuery query = executeSQL(connectionName, strSQL, params); modelID = query.lastInsertId().toInt(); //lasatInsertId()会返回最近插入行的自增id model.id = modelID; } @@ -109,19 +147,19 @@ bool SqlQueryExecutor::addModel(const QString& connectionName, Model& model) return false; } - //然后向mapping_model_group中插入记录 + //然后向model_group中插入记录 for(int groupID : model.groups) { - strSQL = "INSERT INTO basic.mapping_model_group (model_type_id, attribute_group_id) VALUES (" + - QString::number(modelID) + "," + QString::number(groupID) + ")"; - /*strSQL = "INSERT INTO basic.mapping_model_group (model_type_id, attribute_group_id, remark) VALUES " + /*strSQL = "INSERT INTO basic.model_group (model_type_id, attribute_group_id) VALUES (" + + QString::number(modelID) + "," + QString::number(groupID) + ")";*/ + strSQL = "INSERT INTO basic.model_group (model_type_id, attribute_group_id) VALUES " "(:modelID, :groupID)"; params.clear(); params.insert(":modelID", modelID); - params.insert(":groupID", groupID);*/ + params.insert(":groupID", groupID); try { - executeSQL(connectionName, strSQL); + executeSQL(connectionName, strSQL, params); } catch (const DatabaseException& e) { @@ -171,7 +209,18 @@ bool SqlQueryExecutor::modelTypeExistsInDB(const QString& connectionName, const bool SqlQueryExecutor::removeMode(const QString& connectionName, int modelID) { - + QString strSQL = "DELETE FROM basic.model_type WHERE id = :id"/* + QString::number(modelID)*/; + QVariantHash params; + params.insert(":id", modelID); + try + { + executeSQL(connectionName, strSQL, params, true); + } + catch (const DatabaseException& e) + { + return false; + } + return true; } const QVector SqlQueryExecutor::getAttributeGroup(const QString& strConnectionName)