595 lines
21 KiB
C++
595 lines
21 KiB
C++
#include "global.h"
|
||
#include "sqlQueryExecutor.h"
|
||
#include "logger.h"
|
||
#include <QSqlDatabase>
|
||
#include <QDateTime>
|
||
|
||
SqlQueryExecutor& SqlQueryExecutor::instance()
|
||
{
|
||
//采用静态局部变量的方式,静态局部变量的初始化是在第一次访问时,以后的调用不会多次初始化,并且生命周期和程序一致
|
||
static SqlQueryExecutor instance;
|
||
return instance;
|
||
}
|
||
|
||
SqlQueryExecutor::SqlQueryExecutor()
|
||
{}
|
||
SqlQueryExecutor::~SqlQueryExecutor()
|
||
{}
|
||
|
||
//单条SQL语句执行接口
|
||
QSqlQuery SqlQueryExecutor::executeSQL(const QString& connectionName, const QString& strSQL, const QVariantHash& params, bool useTranscation)
|
||
{
|
||
QSqlDatabase db = QSqlDatabase::database(connectionName);
|
||
if(!db.isOpen())
|
||
{
|
||
LOG_ERROR("DB", QString("Database not open. connectionName: %1").arg(connectionName));
|
||
throw DatabaseException(db.lastError());
|
||
}
|
||
|
||
//事务
|
||
bool transactionStarted = false;
|
||
if(useTranscation)
|
||
{
|
||
if(!db.transaction())
|
||
{
|
||
LOG_ERROR("DB", QString("Start transaction failed. connectionName: %1. error: %2").arg(connectionName, 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(connectionName, db.lastError().databaseText()));
|
||
}
|
||
}
|
||
catch (const DatabaseException& e)
|
||
{
|
||
// 错误处理:回滚事务(如果已开启)
|
||
if(transactionStarted)
|
||
{
|
||
LOG_INFO("DB", QString("DB Rollback"));
|
||
if(!db.rollback()) // 回滚失败时记录警告
|
||
{
|
||
LOG_ERROR("DB", QString("Rollback failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
|
||
}
|
||
}
|
||
|
||
throw; // 重新抛出异常
|
||
}
|
||
|
||
return sqlQuery;
|
||
}
|
||
//多条批量SQL语句执行接口
|
||
QSqlQuery SqlQueryExecutor::executeBatchSQL(const QString& connectionName, const QStringList& sqlStatements, const QList<QVariantHash>& paramsList, bool useTranscation)
|
||
{
|
||
QSqlDatabase db = QSqlDatabase::database(connectionName);
|
||
if(!db.isOpen())
|
||
{
|
||
LOG_ERROR("DB", QString("Database not open. connectionName: %1").arg(connectionName));
|
||
throw DatabaseException(db.lastError());
|
||
}
|
||
|
||
//参数数量校验
|
||
if(!paramsList.isEmpty() && sqlStatements.size() != paramsList.size())
|
||
{
|
||
LOG_ERROR("SQL", QString("SQL statement does not match the number of parameters"));
|
||
throw DatabaseException(QSqlError("SQL statement does not match the number of parameters"));
|
||
}
|
||
|
||
//事务
|
||
bool transactionStarted = false;
|
||
if(useTranscation)
|
||
{
|
||
if(!db.transaction())
|
||
{
|
||
LOG_ERROR("DB", QString("Start transaction failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
|
||
throw DatabaseException(db.lastError());
|
||
}
|
||
transactionStarted = true;
|
||
}
|
||
|
||
QSqlQuery lastQuery(db);
|
||
try
|
||
{
|
||
for(int i = 0; i < sqlStatements.size(); i++)
|
||
{
|
||
const QString& strSQL = sqlStatements.at(i);
|
||
const QVariantHash& params = paramsList.isEmpty() ? QVariantHash() : paramsList.at(i);
|
||
|
||
QSqlQuery sqlQuery(db);
|
||
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());
|
||
}
|
||
lastQuery = std::move(sqlQuery);
|
||
// 提交事务(如果已开启)
|
||
if(transactionStarted && !db.commit())
|
||
{
|
||
throw DatabaseException(db.lastError());
|
||
LOG_ERROR("DB", QString("Commit transaction failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
|
||
}
|
||
}
|
||
}
|
||
catch (const DatabaseException& e)
|
||
{
|
||
// 错误处理:回滚事务(如果已开启)
|
||
if(transactionStarted)
|
||
{
|
||
LOG_INFO("DB", QString("DB Rollback"));
|
||
if(!db.rollback()) // 回滚失败时记录警告
|
||
{
|
||
LOG_ERROR("DB", QString("Rollback failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
|
||
}
|
||
}
|
||
|
||
throw; // 重新抛出异常
|
||
}
|
||
|
||
return lastQuery;
|
||
}
|
||
//获取表的字段类型信息(目前只针对PostgerSQL)
|
||
QHash<QString, QString> SqlQueryExecutor::getFiledType(const QString& connectionName, const QString& table, const QString& schema)
|
||
{
|
||
QHash<QString, QString> fieldTypes;
|
||
QString strSQL = QString(
|
||
"SELECT a.attname, pg_catalog.format_type(a.atttypid, a.atttypmod) "
|
||
"FROM pg_catalog.pg_attribute a "
|
||
"JOIN pg_catalog.pg_class c ON a.attrelid = c.oid "
|
||
"JOIN pg_catalog.pg_namespace n ON c.relnamespace = n.oid "
|
||
"WHERE c.relname = LOWER(:table_name) "
|
||
"AND n.nspname = LOWER(:schema_name) "
|
||
"AND a.attnum > 0 AND NOT a.attisdropped;"
|
||
);
|
||
QVariantHash params;
|
||
params.insert(":table_name", table);
|
||
params.insert(":schema_name", schema);
|
||
try
|
||
{
|
||
QSqlQuery query = executeSQL(connectionName, strSQL, params);
|
||
while(query.next())
|
||
fieldTypes.insert(query.value(0).toString(), query.value(1).toString());
|
||
}
|
||
catch (const DatabaseException& e)
|
||
{
|
||
LOG_ERROR("SQL", QString::fromWCharArray(L"获取属性原始数据类型失败"));
|
||
}
|
||
|
||
return fieldTypes;
|
||
}
|
||
|
||
//具体业务查询接口
|
||
const QVector<Model> SqlQueryExecutor::getModels(const QString& connectionName)
|
||
{
|
||
QVector<Model> models;
|
||
QString strSQL = "SELECT id, model_type, model_name, remark FROM basic.model_type ORDER BY id ASC";
|
||
try
|
||
{
|
||
QSqlQuery query = executeSQL(connectionName, 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(connectionName, 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& connectionName, 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(connectionName, 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)
|
||
{
|
||
//属于批量操作,需要开启事务,因为后续插入映射表时需要先插入进model_type记录的自增id,所以无法在一个接口函数中执行,所以事务放在在接口外部执行
|
||
QSqlDatabase db = QSqlDatabase::database(connectionName);
|
||
if(!db.isOpen())
|
||
{
|
||
LOG_ERROR("DB", QString("Database not open. connectionName: %1").arg(connectionName));
|
||
return false;
|
||
}
|
||
|
||
if(!db.transaction())
|
||
{
|
||
LOG_ERROR("DB", QString("Start transaction failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
|
||
return false;
|
||
}
|
||
|
||
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);
|
||
try
|
||
{
|
||
QSqlQuery query = executeSQL(connectionName, strSQL, params);
|
||
modelID = query.lastInsertId().toInt(); //lasatInsertId()会返回最近插入行的自增id
|
||
model.id = modelID;
|
||
}
|
||
catch (const DatabaseException& e)
|
||
{
|
||
LOG_INFO("DB", QString("DB Rollback"));
|
||
if(!db.rollback()) // 回滚失败时记录警告
|
||
{
|
||
LOG_ERROR("DB", QString("Rollback failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
|
||
}
|
||
return false;
|
||
}
|
||
|
||
//然后向model_group中插入记录,采用批量接口
|
||
QStringList sqlStatements;
|
||
QList<QVariantHash> paramsList;
|
||
for(int groupID : model.groups)
|
||
{
|
||
sqlStatements << "INSERT INTO basic.model_group (model_type_id, attribute_group_id) VALUES "
|
||
"(:modelID, :groupID)";
|
||
params.clear();
|
||
params.insert(":modelID", modelID);
|
||
params.insert(":groupID", groupID);
|
||
paramsList << params;
|
||
}
|
||
try
|
||
{
|
||
executeBatchSQL(connectionName, sqlStatements, paramsList);
|
||
}
|
||
catch (const DatabaseException& e)
|
||
{
|
||
LOG_INFO("DB", QString("DB Rollback"));
|
||
if(!db.rollback()) // 回滚失败时记录警告
|
||
{
|
||
LOG_ERROR("DB", QString("Rollback failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
|
||
}
|
||
return false;
|
||
}
|
||
|
||
if(!db.commit()) // 提交
|
||
{
|
||
LOG_ERROR("DB", QString("Commit transaction failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
|
||
return false;
|
||
}
|
||
|
||
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::removeModel(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& connectionName)
|
||
{
|
||
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(connectionName, 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& connectionName, int groupID)
|
||
{
|
||
QString name;
|
||
QString strSQL = "SELECT group_name FROM basic.attribute_group WHERE id = :id";
|
||
QVariantHash params;
|
||
params.insert(":id", groupID);
|
||
try
|
||
{
|
||
QSqlQuery query = executeSQL(connectionName, strSQL, params);
|
||
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;
|
||
}
|
||
|
||
int SqlQueryExecutor::getAttributeCount(const QString& connectionName, int modelID, int groupID)
|
||
{
|
||
int count = 0;
|
||
QString strSQL = QString("SELECT COUNT(*) FROM basic.model_attribute WHERE model_type_id = %1 AND attribute_group_id = %2").arg(modelID).arg(groupID);
|
||
try
|
||
{
|
||
QSqlQuery query = executeSQL(connectionName, strSQL);
|
||
if(query.next())
|
||
count = query.value(0).toInt();
|
||
}
|
||
catch (const DatabaseException& e)
|
||
{
|
||
LOG_ERROR("SQL", QString::fromWCharArray(L"获取属性数量失败"));
|
||
return 0;
|
||
}
|
||
|
||
return count;
|
||
}
|
||
|
||
bool SqlQueryExecutor::getAtrributeInfo(const QString& connectionName, const QString& columns, Attribute& attribute)
|
||
{
|
||
QString strSQL = QString("SELECT %1 FROM basic.attribute WHERE id = %2").arg(columns).arg(attribute.id);
|
||
try
|
||
{
|
||
QSqlQuery query = executeSQL(connectionName, strSQL);
|
||
if(query.next())
|
||
{
|
||
attribute.type = query.value(0).toString();
|
||
attribute.name = query.value(1).toString();
|
||
attribute.dataTypeID = query.value(2).toInt();
|
||
attribute.dataLength = query.value(3).toInt();
|
||
attribute.defaultValue = query.value(4).toString();
|
||
}
|
||
else
|
||
return false;
|
||
}
|
||
catch (const DatabaseException& e)
|
||
{
|
||
LOG_ERROR("SQL", QString::fromWCharArray(L"获取属性数量失败"));
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
bool SqlQueryExecutor::batchInsertAttributes(const QString& connectionName, int modelID, int attributeGroupID, QList<Attribute> attributes)
|
||
{
|
||
//属于批量操作,需要开启事务
|
||
QSqlDatabase db = QSqlDatabase::database(connectionName);
|
||
if(!db.isOpen())
|
||
{
|
||
LOG_ERROR("DB", QString("Database not open. connectionName: %1").arg(connectionName));
|
||
return false;
|
||
}
|
||
|
||
if(!db.transaction())
|
||
{
|
||
LOG_ERROR("DB", QString("Start transaction failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
|
||
return false;
|
||
}
|
||
|
||
//先插入进属性表attribute,因为要获取插入后的自增id,所以采用逐条插入的方法
|
||
QList<qint64> attributeIDList;
|
||
for(const Attribute& atrribute : attributes)
|
||
{
|
||
qint64 attributeID = QDateTime::currentDateTime().toMSecsSinceEpoch();
|
||
//先向model_type中插入一条记录
|
||
QString strSQL = "INSERT INTO basic.attribute (attribute, attribute_name, data_type_id, length_precision, default_value) VALUES "
|
||
"(:type, :name, :dataType, :dataLength, :defaultValue)";
|
||
QVariantHash params;
|
||
params.insert(":type", atrribute.type);
|
||
params.insert(":name", atrribute.name);
|
||
params.insert(":dataType", atrribute.dataTypeID);
|
||
params.insert(":dataLength", atrribute.dataLength);
|
||
params.insert(":defaultValue", atrribute.defaultValue);
|
||
try
|
||
{
|
||
QSqlQuery query = executeSQL(connectionName, strSQL, params);
|
||
attributeID = query.lastInsertId().toInt(); //lasatInsertId()会返回最近插入行的自增id
|
||
}
|
||
catch (const DatabaseException& e)
|
||
{
|
||
LOG_INFO("DB", QString("DB Rollback"));
|
||
if(!db.rollback()) // 回滚
|
||
{
|
||
LOG_ERROR("DB", QString("Rollback failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
|
||
}
|
||
return false;
|
||
}
|
||
attributeIDList.append(attributeID);
|
||
}
|
||
//插入数据到关联表
|
||
QSqlQuery linkQuery(db);
|
||
QString strSQL = "INSERT INTO basic.model_attribute (model_type_id, attribute_group_id, attribute_id) VALUES (?, ?, ?)";
|
||
if(!linkQuery.prepare(strSQL))
|
||
{
|
||
LOG_ERROR("SQL", QString("SQL '%1' prepare fialed. error: %2").arg(strSQL, linkQuery.lastError().databaseText()));
|
||
if(!db.rollback()) // 回滚
|
||
{
|
||
LOG_ERROR("DB", QString("Rollback failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
|
||
}
|
||
return false;
|
||
}
|
||
QVariantList modelIds, groupIds, attributeIds;
|
||
for(const qint64& attributeID : attributeIDList)
|
||
{
|
||
modelIds << modelID;
|
||
groupIds << attributeGroupID;
|
||
attributeIds << attributeID;
|
||
}
|
||
linkQuery.addBindValue(modelIds);
|
||
linkQuery.addBindValue(groupIds);
|
||
linkQuery.addBindValue(attributeIds);
|
||
if( !linkQuery.execBatch() )
|
||
{
|
||
LOG_ERROR("SQL", QString("SQL '%1' execBatch error: %2").arg(strSQL, linkQuery.lastError().databaseText()));
|
||
LOG_INFO("DB", QString("DB Rollback"));
|
||
if(!db.rollback()) // 回滚
|
||
{
|
||
LOG_ERROR("DB", QString("Rollback failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
|
||
}
|
||
return false;
|
||
}
|
||
|
||
if(!db.commit()) // 提交
|
||
{
|
||
LOG_ERROR("DB", QString("Commit transaction failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
bool SqlQueryExecutor::batchDeleteAttributes(const QString& connectionName, int modelID, int attributeGroupID, QList<int> attributes)
|
||
{
|
||
//属于批量操作,需要开启事务
|
||
QSqlDatabase db = QSqlDatabase::database(connectionName);
|
||
if(!db.isOpen())
|
||
{
|
||
LOG_ERROR("DB", QString("Database not open. connectionName: %1").arg(connectionName));
|
||
return false;
|
||
}
|
||
|
||
if(!db.transaction())
|
||
{
|
||
LOG_ERROR("DB", QString("Start transaction failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
|
||
return false;
|
||
}
|
||
|
||
QSqlQuery query(db);
|
||
QString strSQL = "DELETE FROM basic.model_attribute WHERE model_type_id = ? AND attribute_group_id = ? AND attribute_id = ?";
|
||
if(!query.prepare(strSQL))
|
||
{
|
||
LOG_ERROR("SQL", QString("SQL '%1' prepare fialed. error: %2").arg(strSQL, query.lastError().databaseText()));
|
||
if(!db.rollback()) // 回滚
|
||
{
|
||
LOG_ERROR("DB", QString("Rollback failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
|
||
}
|
||
return false;
|
||
}
|
||
QVariantList modelIds, groupIds, attributeIds;
|
||
for(const int& attributeID : attributes)
|
||
{
|
||
modelIds << modelID;
|
||
groupIds << attributeGroupID;
|
||
attributeIds << attributeID;
|
||
}
|
||
query.addBindValue(modelIds);
|
||
query.addBindValue(groupIds);
|
||
query.addBindValue(attributeIds);
|
||
if( !query.execBatch() )
|
||
{
|
||
LOG_ERROR("SQL", QString("SQL '%1' execBatch error: %2").arg(strSQL, query.lastError().databaseText()));
|
||
LOG_INFO("DB", QString("DB Rollback"));
|
||
if(!db.rollback()) // 回滚
|
||
{
|
||
LOG_ERROR("DB", QString("Rollback failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
|
||
}
|
||
return false;
|
||
}
|
||
|
||
if(!db.commit()) // 提交
|
||
{
|
||
LOG_ERROR("DB", QString("Commit transaction failed. connectionName: %1. error: %2").arg(connectionName, db.lastError().databaseText()));
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
}
|