PowerModeler/source/sqlQueryExecutor.cpp

268 lines
8.9 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "global.h"
#include "sqlQueryExecutor.h"
#include "logger.h"
#include <QSqlDatabase>
SqlQueryExecutor& SqlQueryExecutor::instance()
{
//采用静态局部变量的方式,静态局部变量的初始化是在第一次访问时,以后的调用不会多次初始化,并且生命周期和程序一致
static SqlQueryExecutor instance;
return instance;
}
SqlQueryExecutor::SqlQueryExecutor()
{}
SqlQueryExecutor::~SqlQueryExecutor()
{}
//基础SQL语句执行接口
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").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);
try
{
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()));
}
}
catch (const DatabaseException& e)
{
// 错误处理:回滚事务(如果已开启)
if(transactionStarted)
{
if(!db.rollback()) // 回滚失败时记录警告
{
LOG_ERROR("DB", QString("Rollback failed. connectionName: %1. error: %2").arg(strConnectionName, db.lastError().databaseText()));
}
}
throw; // 重新抛出异常
}
return sqlQuery;
}
//具体业务查询接口
const QVector<Model> SqlQueryExecutor::getModels(const QString& strConnectionName)
{
QVector<Model> models;
QString strSQL = "SELECT id, model_type, model_name, remark FROM basic.model_type ORDER BY id ASC";
try
{
QSqlQuery query = executeSQL(strConnectionName, strSQL);
while(query.next())
{
int id = query.value(0).toInt();
QString type = query.value(1).toString();
QString name = query.value(2).toString();
QString remark = query.value(3).toString();
QVector<int> groups = getModelGroups(strConnectionName, id);
models.emplace_back(id, name, type, remark, groups);
}
}
catch (const DatabaseException& e)
{
emit errorOccurred(QString::fromWCharArray(L"获取模型信息失败,详情可见日志文件"));
}
return models; //编译器的RVO/NRVO会自动优化、避免临时拷贝
}
QVector<int> SqlQueryExecutor::getModelGroups(const QString& strConnectionName, int modelID)
{
QVector<int> groups;
QString strSQL = "SELECT attribute_group_id FROM basic.model_group WHERE model_type_id = " + QString::number(modelID);
try
{
QSqlQuery query = executeSQL(strConnectionName, strSQL);
while(query.next())
{
groups.append(query.value(0).toInt());
}
}
catch (const DatabaseException& e)
{
LOG_ERROR("SQL", QString::fromWCharArray(L"获取模型所含属性组名称失败id:%1").arg(QString::number(modelID)));
return groups;
}
return groups;
}
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 "
"(: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 +"\')";*/
try
{
QSqlQuery query = executeSQL(connectionName, strSQL, params);
modelID = query.lastInsertId().toInt(); //lasatInsertId()会返回最近插入行的自增id
model.id = modelID;
}
catch (const DatabaseException& e)
{
return false;
}
//然后向model_group中插入记录
for(int groupID : model.groups)
{
/*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);
try
{
executeSQL(connectionName, strSQL, params);
}
catch (const DatabaseException& e)
{
LOG_ERROR("SQL", QString::fromWCharArray(L"mapping model & group失败, modelID:%1, groupID:%2")
.arg(QString::number(modelID))
.arg(QString::number(groupID)));
continue;
}
}
return true;
}
bool SqlQueryExecutor::modelNameExistsInDB(const QString& connectionName, const QString& name)
{
bool exists = false;
QString strSQL = "SELECT id FROM basic.model_type WHERE model_name = \'" + name + "\'";
try
{
QSqlQuery query = executeSQL(connectionName, strSQL);
if(query.next())
exists = true;
}
catch (const DatabaseException& e)
{
exists = true;
}
return exists;
}
bool SqlQueryExecutor::modelTypeExistsInDB(const QString& connectionName, const QString& type)
{
bool exists = false;
QString strSQL = "SELECT id FROM basic.model_type WHERE model_type = \'" + type + "\'";
try
{
QSqlQuery query = executeSQL(connectionName, strSQL);
if(query.next())
exists = true;
}
catch (const DatabaseException& e)
{
exists = true;
}
return exists;
}
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<AttributeGroup> SqlQueryExecutor::getAttributeGroup(const QString& strConnectionName)
{
QVector<AttributeGroup> groupList;
QString strSQL = "SELECT id, group_type, group_name, remark, is_public FROM basic.attribute_group ORDER BY id ASC";
try
{
QSqlQuery query = executeSQL(strConnectionName, strSQL);
while(query.next())
{
int id = query.value(0).toInt();
QString type = query.value(1).toString();
QString name = query.value(2).toString();
QString remark = query.value(3).toString();
bool isPublic = query.value(4).toBool();
groupList.emplace_back(id,name,type,remark,isPublic); //直接调用构造函数,避免拷贝
}
}
catch (const DatabaseException& e)
{
emit errorOccurred(QString::fromWCharArray(L"获取属性组别信息失败,详情可见日志文件"));
}
return groupList;
}
const QString SqlQueryExecutor::getArributeGropuName(const QString& strConnectionName, int groupID)
{
QString name;
QString strSQL = "SELECT group_name FROM basic.attribute_group WHERE id = " + QString::number(groupID);
try
{
QSqlQuery query = executeSQL(strConnectionName, strSQL);
if(query.next())
name = query.value(0).toString();
}
catch (const DatabaseException& e)
{
LOG_ERROR("SQL", QString::fromWCharArray(L"获取属性组名称失败id:%1").arg(QString::number(groupID)));
name = "groupID-" + QString::number(groupID);
}
return name;
}