将更改提交到 SQLite 数据库,可以在 QTabs 之间看到
Commit changes to SQLite database, that can be seen between QTabs
我有一个简单的应用程序,我可以在其中登录/注销用户。当用户登录时,应用程序会在主窗口上显示相应的选项卡(员工/管理员/客户)。我有一个QMainWindow
,上面有QTabWidget
。在我的QMainWindow
中,我创建了一个数据库(我为此实现了一个特殊的类):
class DataBase
{
public:
DataBase();
void initDatabase();
void closeDatabase();
private:
QSqlDatabase db;
};
DataBase::DataBase()
{
}
void DataBase::initDatabase()
{
QString filename = "database.sql";
QFile file(filename);
db = QSqlDatabase::addDatabase("QSQLITE");
db.setHostName("localhost");
db.setDatabaseName(filename);
// create users table
if(this->db.open())
{
QSqlQuery usersTableQuery;
QString usersTableQueryStr = "CREATE TABLE IF NOT EXISTS USERS (ID INTEGER PRIMARY KEY NOT NULL, "
"LOGIN TEXT,"
"PASSWORD TEXT,"
"FIRSTNAME TEXT,"
"LASTNAME TEXT,"
"EMAIL TEXT,"
"ACCOUNT_TYPE INTEGER"
");";
if(usersTableQuery.exec(usersTableQueryStr))
{
qDebug() << "Create USERS table OK";
}
else
{
qDebug() << usersTableQuery.lastError().text();
}
}
else
{
qDebug() << "DB is not opened!n";
}
// create service table
if(this->db.open())
{
QSqlQuery serviceTableQuery;
QString serviceTableQueryStr = "CREATE TABLE IF NOT EXISTS SERVICE (ID INTEGER PRIMARY KEY NOT NULL, "
"NAME TEXT,"
"PRICE REAL"
");";
if(serviceTableQuery.exec(serviceTableQueryStr))
{
qDebug() << "Create SERVICE table OK";
}
else
{
qDebug() << serviceTableQuery.lastError().text();
}
}
else
{
qDebug() << "DB is not opened!n";
}
}
void DataBase::closeDatabase()
{
db.close();
}
我的员工、管理员、客户的选项卡如下所示:
class AdminTab : public QWidget
{
Q_OBJECT
public:
explicit AdminTab(DataBase *db, QWidget *parent = 0);
//...
每个人(员工,客户,管理员)都可以在数据库中进行更改(例如,管理员可以插入服务,用户可以检查可用的服务等)。但是,当管理员添加服务(我对打开的数据库进行插入操作)并注销时,当客户端登录时,它看不到管理员所做的更改。当我再次启动应用程序并且客户端登录时,它可以看到新添加的服务。
添加服务如下所示:
bool DataBase::insertService(QString name, double price)
{
if(!db.isOpen())
{
qDebug() << query.lastError();
return false;
}
else
{
QSqlQuery query;
query.prepare("INSERT INTO SERVICE (NAME, PRICE) "
"VALUES (:NAME, :PRICE)");
query.bindValue(":NAME", name);
query.bindValue(":PRICE", price);
if(query.exec())
{
return true;
}
else
{
qDebug() << query.lastError();
}
}
return false;
}
我想这是数据库一直打开的问题,但是如何在数据库中插入/删除某些内容后立即进行更改?我在创建数据库时打开数据库QMainWindow
并在其析构函数中关闭它。
每次需要使用它时,我都考虑过打开/关闭数据库,但我不能说这是否是一个好的解决方案。
甚至添加:
if(query.exec())
{
query.clear();
db.commit();
return true;
}
无济于事。
客户端具有:QVector<Service*> availableServices;
和QComboBox *servicesComboBox;
,检查所有可用服务,当客户端登录时:
void ClientTab::updateAllServices()
{
availableServices.clear();
availableServices = db->selectAllServices();
servicesComboBox->clear();
for(int i=0; i<availableServices.size(); i++)
servicesComboBox->addItem(availableServices[i]->getServiceName(), QVariant::fromValue(availableServices[i]));
servicesComboBox->setCurrentIndex(-1);
}
Service
类:
#ifndef SERVICE_H
#define SERVICE_H
#include <QString>
#include <QMetaType>
#include <QVariant>
class Service : public QObject
{
Q_OBJECT
public:
Service(int id, QString name, double price);
Service(){ id = -1; name = ""; price = 0;}
QString getServiceName() const;
void setServiceName(const QString &value);
double getServicePrice() const;
void setServicePrice(double value);
int getId() const;
void setId(int value);
private:
QString name;
double price;
int id;
};
Q_DECLARE_METATYPE(Service*)
#endif // SERVICE_H
最后,从数据库中选择所有服务(我使用此方法填充ClientTab
上的组合框):
QVector<Service*> DataBase::selectAllServices()
{
QVector<Service*> services;
if(!db.isOpen())
{
return services;
}
else
{
QSqlQuery query;
if(query.exec("SELECT * FROM SERVICE;"))
{
while( query.next() )
{
int id = query.value(0).toInt();
QString name = query.value(1).toString();
double price = query.value(2).toDouble();
Service *s = new Service(id, name, price);
services.push_back(s);
}
}
else
{
qDebug() << "DataBase::selectAllServices " << query.lastError();
}
}
return services;
}
你能仔细检查一下吗
void ClientTab::updateAllServices()
每次在客户端登录时调用(不仅在应用程序启动时)?
SQLite 数据库默认具有自动提交功能,因此您无需为这个简单的事情提交任何内容或使用任何事务。
你能看到在 sqlite 命令行中添加的新服务与从服务中选择 * 吗?如果是这样,那么添加一个服务效果很好,你需要检查什么时候调用 updateAllServices()。
如果我正确理解您的问题,那就是关于如何同步数据库的多个视图。这确实是一项艰巨的任务。
如果在任何给定时间只有一个视图可见(就像您在这种情况下使用不同的选项卡一样),只需从数据库重新加载数据并重新填充选项卡即可。你会怎么做?向主窗口添加信号contentChanged()
,并让所有视图在看到数据时重新加载数据。(或者清除其数据并在用户切换到特定选项卡时重新加载。
如果这太慢,或者您可以同时在多个视图中看到相同的内容:您应该使用Qt提供的模型,例如 QListView + QAbstractListModel
而不是QListWidget
.如果使用它们,同步是免费的,但不应再直接访问 SQL 数据库,而只能通过模型进行更改。
- C++中std::resize(n)和std::shrink_to_fit之间的区别
- int(c) 和 c-'0' 之间的区别。C++
- 在cuda线程之间共享大量常量数据
- 在c代码之间共享数据的最佳方式
- Mix_Init和Mix_OpenAudio SDL之间的区别是什么
- C++ 使用 assign 函数的字符串与直接使用 '=' 更改值的字符串之间的区别
- VSOMEIP-2个设备之间的通信(TCP/UDP)不工作
- std::atomic和std::condition_variable wait,notify_*方法之间的区别
- 大小相等但成员数量不同的结构之间的性能差异
- 类与私有变量的其他类之间的线程安全性
- 如何在cpp文件之间切换窗口?在Qt中
- 线程之间的布尔停止信号
- 我是C++编程的新手,这些代码之间有什么区别,我应该使用哪一个
- 在 const 函数中通过引用和指针返回之间的区别
- 我想知道长双倍和双倍之间的区别
- 如何防止clang格式在流运算符调用之间添加换行符<<
- 在两台机器之间进行时间戳的最佳c++chrono函数是什么
- 使用.find函数在c++中查找字符和另一个字符之间的大小
- 构造函数和转换运算符之间的重载解析
- 将更改提交到 SQLite 数据库,可以在 QTabs 之间看到