私はマニュアルと混同しました、私はこのように働くべきですか:
_{
QSqlDatabase db = QSqlDatabase::addDatabase (...);
QSqlQuery query (db);
query.exec (...);
}
QSqlDatabase::removeDatabase (...);
_
ドキュメントが指摘しているように、query
またはdb
は自動的に分解されます。しかし、それは効率的ですか?
さて、次のようにdb
をクラス内にキャッシュすると:
_class Dummy {
Dummy() {
db = QSqlDatabase::addDatabase (...);
}
~Dummy() {
db.close();
}
bool run() {
QSqlQuery query (db);
bool retval = query.exec (...);
blabla ...
}
private:
QSqlDatabase db;
};
_
次のような警告が表示される場合があります。
_QSqlDatabasePrivate::removeDatabase: connection 'BLABLA' is still in use, all queries will cease to work.
_
run()
を呼び出さなかったとしても。
QSqlDatabase
でaddDatabase
オブジェクトを作成するとき、またはremoveDatabase
を呼び出すときは、単にタプルを関連付けまたは関連付け解除します(driver、hostname:port、database name 、ユーザー名/パスワード)名前(または、接続名を指定しない場合はデフォルトの接続名)。
SQLドライバーはインスタンス化されますが、データベースは_QSqlDatabase::open
_を呼び出したときにのみ開かれます。
その接続名はアプリケーション全体で定義されます。したがって、それを使用する各オブジェクトでaddDatabase
を呼び出すと、同じ接続名を使用するすべてのQSqlDatabase
オブジェクトを変更し、それらでアクティブだったすべてのクエリを無効にします。
最初に引用したコード例は、次のことを確認することにより、接続名を正しく関連付ける方法を示しています。
QSqlQuery
は、QSqlDatabase
オブジェクトがスコープ外になったときに自動的に実行されるQSqlQuery::finish()
を呼び出すことにより、データベースを閉じる前にQSqlQuery
から切り離されます。QSqlDatabase
は、QSqlDatabase::removeDatabase
_を呼び出すとclose()
dです(QSqlDatabase
オブジェクトが移動すると、close()
も自動的に呼び出されます範囲外)。QSqlDatabaseを作成するとき、アプリケーションの有効期間中接続を開いたままにするか(1)、必要なときだけ接続するか(2)に応じて、次のことができます。
単一のQSqlDatabase
インスタンスを単一のクラス(たとえばメインウィンドウ)に保持し、QSqlDatabase
を直接渡すか、接続名のみを渡すことで、それを必要とする他のオブジェクトで使用します。 _QSqlDatabase::database
_に渡して、QSqlDatabase
インスタンスを取得します。 _QSqlDatabase::database
_はQHash
を使用してその名前からQSqlDatabase
を取得するため、QSqlDatabase
オブジェクトをオブジェクトと関数間で直接渡すよりもおそらく無視できるほど遅いです。デフォルトの接続を使用する場合、どこにも何も渡す必要はなく、パラメータなしでQSqlDatabase::database()
を呼び出すだけです。
_// In an object that has the same lifetime as your application
// (or as a global variable, since it has almost the same goal here)
QSqlDatabase db;
// In the constructor or initialization function of that object
db = QSqlDatabase::addDatabase("QSQLDRIVER", "connection-name");
db.setHostname(...);
// ...
if(!this->db.open()) // open it and keep it opened
{
// Error handling...
}
// --------
// Anywhere you need it, you can use the "global" db object
// or get the database connection from the connection name
QSqlDatabase db = QSqlDatabase::database("connection-name");
QSqlQuery query(db);
_
QSqlDatabase
を一度設定し、それを開いてパラメータが正しいことをテストし、インスタンスを捨てます。接続名はどこからでもアクセスできますが、データベースを再度開く必要があります。
_{
// Allocated on the stack
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLDRIVER", "connection-name");
db.setHostname(...);
// ...
if(!this->db.open()) // test the connection
{
// Error handling
}
// db is closed when it goes out of scope
}
{
// Same thing as for (1), but by default database() opens
// the connection if it isn't already opened
QSqlDatabase db = QSqlDatabase::database("connection-name");
QSqlQuery query(db);
// if there is no other connection open with that connection name,
// the connection is closed when db goes out of scope
}
_
その場合、同じデータベース接続を再入可能な方法で使用する複数のオブジェクトを持つことができるため、データベースを明示的に閉じてはならないことに注意してください(たとえば、関数Aが接続を使用し、接続も使用するBを呼び出す場合)。 BがAに制御を返す前に接続を閉じると、Aの接続も閉じられますが、これはおそらく悪いことです。
QSqlDatabaseとQSqlQueryは具体的な実装の軽量ラッパーなので、最初の例で問題ありません。接続の追加時に名前を指定するか、デフォルトのデータベースを使用する場合、「QSqlDatabase db(name)」と記述するだけで、ほとんどオーバーヘッドのないデータベースオブジェクトが得られます。
removeDatabaseは、ファイル(sqliteの場合)または接続(ODBC/MySql/Postgresの場合)を閉じることと同等であるため、通常はプログラムの終了時に実行します。警告にあるように、そのデータベースを参照するすべてのデータベースとクエリオブジェクトは、既に破棄されているか、悪いことが起こる可能性があることを確認する必要があります。
命令は、以下の順序で正確に実行する必要があります。そうしないと、データベース接続またはクエリで問題が発生します。これはQt5で機能します。
QSqlQueryModel *model = new QSqlQueryModel;
db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName(fileName);
if (db.isValid())
{
db.open();
if (db.isOpen())
{
QSqlQuery searchQuery(db);
searchQuery.prepare("SELECT * FROM myTable");
searchQuery.exec();
if(searchQuery.isActive())
{
model->setQuery(searchQuery);
sui->DBDisplay->setModel(model);
db.close();
} else {
qDebug() << "query is not active";
}
} else {
qDebug() << "DB is not open";
}
} else {
qDebug() << "DB is not valid";
}