dudas con clases y sus instancias
-
hola gente!! saludo desde chile.
Les comento que estoy trabajando con Qt5. y estoy teniendo serias dudas sobre las clases.
resulta que estoy trabajando con una dblite y va de los mas bien, pero me salto unas dudas. Les comento un poco, tengo 3 form, (fm1, fm2 y fm3) mas una clase que realice para manejar la base de datos. En mi fm1 inicializo mi db, creo la tabla y dejo datos por defectos y cierro conexión db.close();. hasta aquí vamos super bien, pero al pasar a mi fm2 me sale un mensaje en mi qDebug()1-Sqlite Connection: QSqlError("", "", "") 2-QSqlDatabasePrivate::addDatabase: duplicate connection name 'qt_sql_default_connection', old connection removed. 3-Sqlite Connection: QSqlError("", "", "") 4-"SELECT nombre FROM usuarios"
la primera linea se por que es. reviso con "SELECT * FROM dd" si esta creada la tabla 'dd' y así saber que tengo que ingresar unos datos criticos. pero no se por que se debe las otras lineas. en mi boton que uso para pasar a mi fm2 tengo:
#include "fm2" void MainWindow::on_btn_fm2_clicked() { fm2 *nextfm = new fm2(this); nextfm->setModal(true); nextfm->show();
y en mi fm2 tengo:
#include "fm3" y un boton igual al de arriba pero que apunta a mi fm3
luego en mi fm3 tengo:
fm2::fm2(QWidget *parent) : QDialog(parent), ui(new Ui::fm2) { ui->setupUi(this); Sqlite_Class LoadcbUser; LoadcbUser.sql_select("nombre","usuarios",""); while(LoadcbUser.sql_getResults().next()) { ui->cb_User->addItem(LoadcbUser.sql_getResults().value(0).toString()); } LoadcbUser.sql_close();//*/ ui->cb_User->addItem("Llave Acceso"); }
uso estas lineas para extraer de mi base de datos los usuarios ingresados y pasarlas a un QCombobox; Ahora del mensaje de error la linea 4 es donde pregunto a mi bd sobre los usuarios, pero mi duda es justamente esta. por que se me ejecuta la pregunta a la db si aún no presiono el boton para pasar al fm3? ahora si presiono el boton se le agrega otro mensaje de erro proveniente de mi qDebug:
QSqlDatabasePrivate::addDatabase: duplicate connection name 'qt_sql_default_connection', old connection removed. Sqlite Connection: QSqlError("", "", "") "SELECT nombre FROM usuarios"
Pero lo raro es que si miro mi QCombobox se cargo correctamente con los usuarios.
La pregunta en concreto es por que se me esta instanciando dos veces la petición de ir a buscar datos a mi db? -
Hola
Veo que estás usando alguna librería que no pertenece a Qt para conectar con la base de datos. No la conozco, por tanto lo que te recomiendo es que vayas a su documentación para ver la forma de uso.
Personalmente uso la que ya trae Qt, que son muchas y cubren casi todos los aspectos que puedas necesitar, desconozco totalmente esas y las ventajas que aportan sobre las clases de Qt.
El error que te está dando es que estás creando dos conexiones a la base de datos con el mismo nombre. En Qt, cuando creas una conexión con la base de datos puedes darle un nombre, así puedes tener varias simultaneas, si no lo haces Qt le asigna un nombre por defecto y si vuelves a crear otra y tampoco le das el nombre, sale ese aviso.
Básicamente la forma de trabajar con las bases de datos en Qt es:
Primero crear una conexión con la base de datos, es algo que se hace una sola vez. Yo suelo hacerlo en el método main, así de paso hago comprobaciones y si hay error al conectar, pues muestro un mensaje de error y no cargo la ventana principal (por ejemplo).
Luego, en cualquier parte de tu programa que quieras acceder a la base de datos, tan solo tienes que obtener una referencia la conexión antes creada y ya puedes acceder a los datos.
Te recomiendo que te mires la documentación de Qt al respecto:
http://doc.qt.io/qt-5/qtsql-module.html
http://doc.qt.io/qt-5/examples-sql.htmlUn saludo
-
hola Juanki, gracias por la respuesta. te comento que yo genere una clase llamada sqlite_class, y en ella tengo:
en el Sqlite_Class.hclass Sqlite_Class { public: Sqlite_Class(); int sql_insert(QString table, QStringList data, QStringList values); int sql_select(QString select, QString from, QString where); int sql_update(QString table, QStringList data, QStringList values, QString where); int sql_delete(QString table, QString where); void sql_close(); bool sql_open(); QString sql_Init(); QSqlQuery sql_getResults(); QSqlError sql_getLastError(); private: QSqlQuery query; QSqlDatabase db; };
y en el Sqlite_Class.cpp
Sqlite_Class::Sqlite_Class() { db = QSqlDatabase::addDatabase("QSQLITE"); db.setDatabaseName(DBName); if(!db.open()) { qDebug() << "Sqlite Connection: " <<db.lastError(); } QSqlQuery qry; query = qry; } ........
ahora me queda una duda con lo que dices
Cita:solo tienes que obtener una referencia la conexión antes creada
como hago esto?
Ahora como lo dices tu, cambie mi inicio de conexión al main con:Sqlite_Class iniciar_db; QString mesaje_Error = iniciar_db.sql_Init(); if(mesaje_Error!= ""){ QMessageBox::warning(0,"SQL ERROR",mesaje_Error); }
al hacer esto ahora me arroja otro error al presionar el btn que accede a mi fm2:
QSqlDatabasePrivate::removeDatabase: connection 'qt_sql_default_connection' is still in use, all queries will cease to work. QSqlDatabasePrivate::addDatabase: duplicate connection name 'qt_sql_default_connection', old connection removed. "SELECT nombre FROM usuarios"
por que me sale eso ahora?
saludos y gracias por el tiempo..
-
Hola @japifer said
Ah, vale, que la has hecho tu, pensaba que era una librería. Por lo que veo, el problema lo tienes en el constructor, que dentro de el es donde creas la conexión con la base de dato, por lo tanto, cada vez que creas una instancia de tu clase estás creando una nueva conexión y por eso te sale el aviso.
Lo que yo haría es crear la conexión en el método main y en el constructor de tu clase simplemente obtener una referencia dicha conexión. Te pongo un ejemplo que soy muy malo explicando, en el método main pondría algo así:
// conexión con la base de datos SQLite QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"); db.setDatabaseName("nombre_de_tu_archivo.sqlite"); if(!db.open()) { qDebug() << "Error al abrir la base de datos: " << db.lastError().text(); return EXIT_FAILURE; } // crear las tablas si no existen if(db.tables().isEmpty()) { QSqlQuery consulta(db); if(!consulta.exec("CREATE TABLE ....")) { qDebug() << "Error al crear la tablas: " << consulta.lastError().text(); return EXIT_FAILURE; } }
Y modificamos el constructor de tu clase para obtener la referencia:
Sqlite_Class::Sqlite_Class()
{
db = QSqlDatabase::database();}
Con esto ya debería, si no hay más errores por ahí, funcionarte. Ojo, no llames a QSqlDatabase::removeDatabase dentro de tu clase, ni en el destructor, si no, cuando vayas a crear otra instancia de tu clase ya no existirá la conexión y tendrás un error. En general no es necesario llamar a éste método, salvo en ocasiones especiales.
Un saludo
-
Hoa Juanki, mira ya saque el ERROR, ojo que esto igual me dejaba andar y funcionar el programa....
pude sacar este error agregando en mi class Sqlite_class en la parte que cierro conexiones esto:
void Sqlite_Class::sql_close() { query.clear(); query.finish(); QString NameConect; NameConect = db.connectionName(); db.close(); db = QSqlDatabase(); db.removeDatabase(NameConect); //return db.close(); }
con esto ya no tengo problemas..
Juanki gracias por el tiempo dedicado se agradece de antemanos.
-
Hola @japifer
Ahí el problema que veo es que estás creando (en el constructor) y eliminando (en ese método) la conexión con la base de datos, así, cada vez que creas una instancia de tu clase creas y luego eliminas la conexión, con la forma que yo te proponía se crea la conexión una vez al principio y luego se usa donde quieras. Es la forma que he visto en los ejemplos de Qt, aunque no soy ningún experto para ver cual es la mejor forma. No estaría mal que alguien con más conocimientos pase y nos aclare, ya que hace poco había otro usuario que hacía igual que tu.
Esta línea no la entiendo:
db = QSqlDatabase();
Si db ya apunta a la base de datos (lo hiciste en el constructor) ¿Por qué esa línea?
Un saludo
-
Hola, esa linea se me paso jajaj
db = QSqlDatabase();
era antes de pasarla al constructor. y bueno yo siempre acostumbro a abrir y cerra la conexión a la db, por petición. no se si esto sera lo correcto o no pero es algo que hago.. esto es por que me da miedo que el programa en algún momento se me cuelgue y deje la db tomada y otros programas no puedan acceder a la db, o el demonio en python que tengo corriendo por debajo de Qt.. jajaj
pero como bien dices tu, seria bueno que algún experto nos pueda aclarar la mejor forma de poder acceder a la db.Saludos y reitero las gracias por el tiempo dedicado.
-
Hola
Con ese planteamiento el problema que tienes es que solo puedes tener una instancia de tu clase a la vez, por que estás usando la conexión por defecto y si creas una segunda clase, te saldrá el aviso y podrás tener algún error con las consultas en la primera clase.
Lo que puedes hacer es modificar el constructor para que acepte un parámetro de QString que sea al nombre que le des a la conexión y así usas conexiones con nombre y podrás tener a la vez las que quieras.
Un saludo