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