事务的最大的功能就是保证数据库操作的原子性。
启动事务之后,如果没有异常,则可以正常提交;如果操作过程中有任何的异常,则回滚至开始的状态。
Qt的数据库事务操作示例代码如下(仅做演示用,没有进行相应的判断功能):
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QMessageBox>
#include <QSqlDriver>
#include "QSqlTest.h"
const QString DB_CONNECT_NAME = "db_test.db";
#define PTR_SAFE_DELETE(ptr) if (nullptr != (ptr)) { delete (ptr); (ptr) = nullptr; }
class QSqlTestPrivate
{
public:
QSqlDatabase m_db;
bool m_ok;
};
QSqlTest::QSqlTest(QWidget *parent)
: QMainWindow(parent)
, d_ptr(new QSqlTestPrivate)
{
ui.setupUi(this);
connect(ui.insertBtn, SIGNAL(clicked()), this, SLOT(onInsertBtnClicked()));
connect(ui.clearBtn, SIGNAL(clicked()), ui.plainTextEdit, SLOT(clear()));
connect(ui.getBtn, SIGNAL(clicked()), this, SLOT(onGetBtnClicked()));
ui.plainTextEdit->setReadOnly(true);
d_ptr->m_db = QSqlDatabase::addDatabase("QSQLITE", DB_CONNECT_NAME);
d_ptr->m_db.setDatabaseName(DB_CONNECT_NAME);
d_ptr->m_ok = d_ptr->m_db.open();
if (d_ptr->m_ok)
{
if (d_ptr->m_db.tables().isEmpty())
{
initDb();
}
else
{
auto list = d_ptr->m_db.tables();
for (const auto& tab : list)
{
ui.plainTextEdit->appendPlainText(tab);
}
}
}
}
QSqlTest::~QSqlTest()
{
if (d_ptr->m_ok)
{
d_ptr->m_db.close();
d_ptr->m_ok = false;
}
PTR_SAFE_DELETE(d_ptr)
}
void QSqlTest::onInsertBtnClicked()
{
if (d_ptr->m_ok)
{
// 判断驱动是否支持事务操作
if (d_ptr->m_db.driver()->hasFeature(QSqlDriver::Transactions))
{
// 启动事务
if (d_ptr->m_db.transaction())
{
QSqlQuery query(d_ptr->m_db);
QString sql = QString("insert into db_info_test values('%1')").arg(ui.lineEdit->text());
if (!query.exec(sql))
{
QMessageBox::warning(this, "insert", query.lastError().text());
}
// 提交操作
if (!d_ptr->m_db.commit())
{
QMessageBox::warning(this, "commit", "commit failed");
// 提交失败,则回滚
if (!d_ptr->m_db.rollback())
{
QMessageBox::warning(this, "rollback", "rollback failed");
}
}
}
}
else
{
QMessageBox::information(this, "transaction", "current sql driver not support transaction");
}
}
}
void QSqlTest::onGetBtnClicked()
{
if (d_ptr->m_ok)
{
QSqlQuery query(d_ptr->m_db);
QString sql("select * from db_info_test");
if (query.exec(sql))
{
while (query.next())
{
ui.plainTextEdit->appendPlainText(query.value(0).toString());
}
}
}
}
void QSqlTest::initDb()
{
if (d_ptr->m_ok)
{
QSqlQuery query(d_ptr->m_db);
QString sql("create table db_info_test(data test not null)");
if (!query.exec(sql))
{
QMessageBox::warning(this, "create table", "create table failed.");
}
else
{
QMessageBox::information(this, "create table", "create table successful.");
}
}
}