Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Update: Forum Guidelines & Code of Conduct

    [Решен] Постоянна mysql връзка

    Bulgarian
    2
    5
    5470
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • R
      Robbin last edited by

      Здравейте.

      Вече в няколко проекта срещам проблем със свързаността към 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 заявка работеща на дадената връзка, така че метода е възможен, но ме притеснява "разхода" на ресурси и скоростта на работа.

      1 Reply Last reply Reply Quote 0
      • T
        task_struct last edited by

        Здравей,

        и аз си играя с подобни неща за дипломната ми работа. Не съм ги тествал, защото така и няма да ме накарат да я пусна :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(), когато се появи пак връзка. По-чисто ще стане така, според мен ;)

        "Most good programmers do programming not because they expect to get paid or get adulation by the public, but because it is fun to program."

        • Linu...
        1 Reply Last reply Reply Quote 0
        • R
          Robbin last edited by

          Здрасти.

          Мерси за мнението и предложенията.
          В интерес на истината, 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() може и да не затвори връзката ако има все още работещи заявки. Шанс едно на милион, но може да създаде проблеми....

          1 Reply Last reply Reply Quote 0
          • R
            Robbin last edited by

            Оказа се че проблема има много просто решение, но човек трябва да седне и да прочете малко документацията /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 клиента да се реконектне, след което всичко се оправя.

            В моя случай това ще ми свърши работа, надявам се и за други да е полезно ;-)

            1 Reply Last reply Reply Quote 0
            • R
              Robbin last edited by

              Всъщност явно "=1" е необходимо, защото след следващата компилация почна да ми хвърля грешки. Така че правилния синтаксис си остава option=value или примерно

              @
              db.setConnectOptions("MYSQL_OPT_RECONNECT=1;CLIENT_SSL=1");
              @

              1 Reply Last reply Reply Quote 0
              • First post
                Last post