hasnext example database qt qt4 qtsql

example - ¿Cuál es la forma correcta de QSqlDatabase y QSqlQuery?



qt sql connection (3)

Cuando crea un objeto QSqlDatabase con addDatabase o cuando llama a removeDatabase , simplemente está asociando o desasociando una tupla (controlador, nombre de host: puerto, nombre de base de datos, nombre de usuario / contraseña) a un nombre (o al nombre de conexión predeterminado si no lo hace) t especificar un nombre de conexión).
El controlador SQL se instancia, pero la base de datos solo se abrirá cuando llame a QSqlDatabase::open .

Ese nombre de conexión se define en toda la aplicación. Por lo tanto, si llama a addDatabase en cada uno de los objetos que lo usan, está cambiando todos los objetos QSqlDatabase que usan el mismo nombre de conexión e invalidando todas las consultas que estuvieron activas en ellos.

El primer ejemplo de código que citó muestra cómo desasociar correctamente el nombre de la conexión, asegurándose de que:

  • todos los QSqlQuery se separan de QSqlDatabase antes de cerrar la base de datos llamando a QSqlQuery::finish() , que es automático cuando el objeto QSqlQuery queda fuera del alcance,
  • todas las QSqlDatabase con el mismo nombre de conexión son close() d cuando llama a QSqlDatabase::removeDatabase ( close() también se llama automáticamente cuando el objeto QSqlDatabase sale del alcance).

Cuando crea la base QSqlDatabase, dependiendo de si desea que la conexión permanezca abierta durante la vida útil de la aplicación (1) o cuando sea necesario (2), puede:

  1. mantenga una única instancia de QSqlDatabase en una sola clase (por ejemplo, en su ventana principal) y úsela en otros objetos que la necesiten pasando la base de datos QSqlDatabase directamente o solo el nombre de conexión que pasa a QSqlDatabase::database para obtener la QSqlDatabase::database de QSqlDatabase::database QSqlDatabase instancia de vuelta. QSqlDatabase::database usa QHash para recuperar una QSqlDatabase de su nombre, por lo que es probablemente más lento que pasar el objeto QSqlDatabase directamente entre objetos y funciones, y si usas la conexión predeterminada, ni siquiera tienes que pasar nada por ningún lado , simplemente llame a QSqlDatabase::database() sin ningún parámetro.

    // 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);

  2. configure QSqlDatabase una vez, ábralo para probar que los parámetros son correctos y elimine la instancia. El nombre de la conexión seguirá estando accesible en cualquier lugar, pero la base de datos tendrá que volver a abrirse:

    { // 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 }

    En ese caso, tenga en cuenta que no debe cerrar la base de datos explícitamente, porque puede tener múltiples objetos usando la misma conexión de base de datos en una forma reentrante (por ejemplo, si una función A usa la conexión y llama a B que también usa la conexión. Si B cierra la conexión antes de devolver el control a A, la conexión también se cerrará para A, lo que probablemente sea algo malo).

Me confundí con el manual, debería funcionar así:

{ QSqlDatabase db = QSqlDatabase::addDatabase (...); QSqlQuery query (db); query.exec (...); } QSqlDatabase::removeDatabase (...);

Como se señala en el documento, query o db se deconstruirán automáticamente. Pero es eso eficiente?

Bueno, si guardo db dentro de una clase, como el siguiente:

class Dummy { Dummy() { db = QSqlDatabase::addDatabase (...); } ~Dummy() { db.close(); } bool run() { QSqlQuery query (db); bool retval = query.exec (...); blabla ... } private: QSqlDatabase db; };

A veces puedo ver advertencias como:

QSqlDatabasePrivate::removeDatabase: connection ''BLABLA'' is still in use, all queries will cease to work.

Incluso si no llamé a run() .


Encuentro que las instrucciones deben ejecutarse exactamente en el orden en que se encuentran a continuación o si tiene problemas, ya sea con la conexión de la base de datos o la consulta. Esto funciona en 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"; }


QSqlDatabase y QSqlQuery son envoltorios livianos en implementaciones concretas, por lo que su primer ejemplo está bien. Si proporciona un nombre al agregar la conexión, o utiliza la base de datos predeterminada, simplemente escribiendo ''QSqlDatabase db (name)'' le proporciona el objeto de base de datos con muy poca sobrecarga.

removeDatabase es equivalente a cerrar el archivo (para sqlite) o la conexión (para ODBC / MySql / Postgres), por lo que suele ser algo que haría al finalizar el programa. Como dice la advertencia, debe asegurarse de que todos los objetos de bases de datos y consultas que se refieren a esa base de datos ya se hayan destruido o que sucedan cosas malas.