4

ユーザーをログイン/ログアウトできるシンプルなアプリケーションがあります。ユーザーがログインすると、アプリケーションはメイン ウィンドウ (従業員/管理者/顧客) に適切なタブを表示します。私はそれを持ってQMainWindowQTabWidgetます。私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;
}
4

2 に答える 2

1

それを再確認していただけますか

void ClientTab::updateAllServices()

クライアントがログインするたびに(アプリケーションの開始時だけでなく)呼び出されますか?

SQLite データベースはデフォルトで自動コミットがオンになっているため、この単純なことのために何もコミットしたり、トランザクションを使用したりする必要はありません。

select * from service を使用して sqlite コマンド ラインに追加された新しいサービスを確認できますか? その場合、サービスの追加はうまくいきます。いつ updateAllServices() を呼び出すかを確認する必要があります。

于 2016-02-23T01:32:40.253 に答える