Ответ 1
Когда вы создаете объект QSqlDatabase
с помощью addDatabase
или когда вы вызываете removeDatabase
, вы просто связываете или отключаете кортеж (драйвер, имя хоста: порт, имя базы данных, имя пользователя/пароль) до имени (или к имени подключения по умолчанию, если вы не укажете имя подключения).
Создан экземпляр SQL-драйвера, но база данных будет открыта только при вызове QSqlDatabase::open
.
Это имя соединения определено в приложении. Поэтому, если вы вызываете addDatabase
в каждом из объектов, которые его используют, вы меняете все объекты QSqlDatabase
, которые используют одно и то же имя соединения, и аннулируют все активные запросы на них.
В приведенном выше примере кода показано, как правильно отключить имя соединения, указав, что:
- all
QSqlQuery
отсоединяются отQSqlDatabase
до закрытия базы данных, вызываяQSqlQuery::finish()
, которая автоматически, когда объектQSqlQuery
выходит за пределы области видимости, - all
QSqlDatabase
с тем же именем соединенияclose()
d при вызовеQSqlDatabase::removeDatabase
(close()
также вызывается автоматически, когда объектQSqlDatabase
выходит за пределы области видимости).
Когда вы создаете 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, что, вероятно, является плохим).