[Решен] Постоянна mysql връзка
-
Здравейте.
Вече в няколко проекта срещам проблем със свързаността към mysql.
Не намирам никакъв начин за проверка дали връзката към базата не се е разпаднала преди да се изпълни заявка. Направил съм следното:
@
QSqlDatabase Common::getDatabase()
{
QSqlDatabase db;
if( QSqlDatabase::contains("connname") && QSqlDatabase::database("connname").isValid() ) {
db = QSqlDatabase::database("connname");
} else {
db = QSqlDatabase::addDatabase("QMYSQL", "connname");
db.setHostName("dhhost");
db.setDatabaseName("connname");
db.setUserName("dbuser");
db.setPassword("dbpass");
db.open();
}return db;
}
@Класа "Common" има само статични методи, с идеята да мога да ги викам от всяка част на програмата, без да правя обекти само заради една функция. Ползвам го по следния начин:
@
QSqlQuery query( Common::getDatabase() );
query.exec("SELECT * FROM `table");
@Когато връзката към базата не е нарушена от пускането на програмата до спирането и, всичко е наред и с тези функции работят нещата. Но ако връзката прекъсне (свързване към друг доставчик, VPN, спиране на мрежов кабел и други), програмата чака query.exec да приключи, който пък не може да приключи заради нарушената връзка. Търсих какви ли не варианти, isValid() и isOpen() на QSqlDatabase винаги връщат true и с тях не може да се проверява състоянието на връзката.
Някой от вас намерил ли е решение на този проблем? Единственото което ми идва на ум е да направя wrapper клас който да викам при нови заявки към базата и в него да стартирам конекцията и да я спирам веднага след като заявката приключи. Това разбира се ще дойде и с големия overhead за отваряне на нова конекция всеки път и според мен не е решение. Едва ли във всеки един момент ще имам повече от 1 заявка работеща на дадената връзка, така че метода е възможен, но ме притеснява "разхода" на ресурси и скоростта на работа. -
Здравей,
и аз си играя с подобни неща за дипломната ми работа. Не съм ги тествал, защото така и няма да ме накарат да я пусна :D
Но като цяло за мрежата може да следиш с @QNetworkAccessManager::networkAccessibleChanged@ Според документацията е добре всяка програма да има само една инстанция на QNetworkAccessManager за това аз си го правя глобална променлива и си я достъпвам от където ми трябва. При този сигнал, когато се появи мрежа може да отваряш базата на ново.
Друго, което мога да те посъветвам е за QSqlDatabase e, да не правиш допълнителен клас.
Можеш спокойно в main преди да стартираш всичко да извикаш @QSqlDatabase db = QSqlDatabase::addDatabase( "QMYSQL", "connname" );@ Това ще съдаде DB с такова име в някакъв глобален лист. После може да си я достъпваш от там с @QSqlDatabase db = QSqlDatabase::database("connname");@
Още след създаването на базата и подаваш:
@
db.setHostName("dhhost");
db.setDatabaseName("connname");
db.setUserName("dbuser");
db.setPassword("dbpass");
@
От там нататък той си ги знае и само ще викаш open(), когато се появи пак връзка. По-чисто ще стане така, според мен ;) -
Здрасти.
Мерси за мнението и предложенията.
В интерес на истината, QNAM използвам на едно единствено място, заедно с WebKit. Това обаче е отделно от това за което ми трябва проверка на връзката с базата. Забравил съм да спомена че базата се намира на отдалечен сървър и идеята е да може да се свързва и тегли информация от нея без значение на какъв интернет се намира клиента и при срив на връзката тя да се възстановява.Създаването и отварянето на базата ми се намираха в main, но унифицирах всичко в Common класа, тъй като навсякъде трябваше да повтарям упражнението
@
QSqlDatabase db = QSqlDatabase::database("connname");
QSqlQuery query(db);
@Вярно, не ми съкращава много кода, но според мен с ползването на функцията Common::getDatabase() е по- "чисто".
За предложението за networkAccessibleChanged намерих "това":http://stackoverflow.com/questions/18365382/how-do-i-get-a-signal-from-qnetworkaccessmanagernetworkaccessiblechanged
Не ми изглежда да работи коректно, когато има повече от един мрежов интерфейс.... Ще трябва да тествам. Иначе предполагам мога просто с QNAM да проверявам дали въобще имам връзка преди да правя заявки към базата, защото когато програмата стигне до query.exec() просто си забива - таймаута е твърде голям и не намерих начин да го променя :(
Иначе според теб дали овърхеда за постоянно отваряне и затваряне на връзката към базата ще е проблем? Имам предвид, както писах и в първия пост, да направя отделен клас (или да субкласна QSqlDatabase), от където вече да си изпълнявам заявките на принципа на работа примерно на PHP - без постоянна връзка, когато има заявка - свързва се, изпълнява я, връща резултата и затваря всичко. Дали няма да забавя излишно програмата по тоя начин и да увелича използването на ресурсите? Притеснява ме че QSqlDatabase::close() може и да не затвори връзката ако има все още работещи заявки. Шанс едно на милион, но може да създаде проблеми.... -
Оказа се че проблема има много просто решение, но човек трябва да седне и да прочете малко документацията /facepalm/
Ето извадка от документацията:
@
void QSqlDatabase::setConnectOptions ( const QString & options = QString() )Sets database-specific options. This must be done before the connection is opened or it has no effect (or you can close() the connection, call this function and open() the connection again).
@Към тази функция са описани всички опции които потдържа съответния клиент. За MySQL има MYSQL_OPT_RECONNECT.
На същото място има дадени примери
@
...
// MySQL connection
db.setConnectOptions("CLIENT_SSL=1;CLIENT_IGNORE_SPACE=1"); // use an SSL connection to the server
if (!db.open()) {
db.setConnectOptions(); // clears the connect option string
...
}
...
@
В примера използват option=value синтаксис, но проверих (специално за MySQL) дали става ако само се подадат опциите (без "=1") - всичко е ОК, дори и да се смени доставчика или интернета да е прекъснал за момент, клиента се реконектва и няма проблеми. Ако се загуби връзката, програмата "заспива" и чака MySQL клиента да се реконектне, след което всичко се оправя.В моя случай това ще ми свърши работа, надявам се и за други да е полезно ;-)