在使用Qt Qml编写某一个服务器时,使用之前的热加载便于在Sql报错时输出哪些地方出了问题并可以排查,主要在重载Server时Sql initdb这里会警告提示,提示代码如下
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.
貌似对查询结果没有影响,当使用类似于QSqlDatabase::removeDatabase("qt_sql_default_connection"); 可以消除第二个警告,无法消除第一个警告,不知道为啥。
其中,sql处理类的初始化这里
QSqlError DatabaseManager::initdb()
{
// QSqlDatabase::removeDatabase("qt_sql_default_connection");
// 可以在重载Server时消除警告QSqlDatabasePrivate::addDatabase: duplicate connection name 'qt_sql_default_connection', old connection removed.
db = QSqlDatabase::addDatabase("QMYSQL");
db.setHostName("localhost");
db.setPort(xxx);
db.setUserName("xx");
db.setPassword("xxx");
db.setDatabaseName("xxx");
if(!db.open())
{
return db.lastError();
}
emit connectedSql();
}
用于调试的代码如下:
QSqlError DatabaseManager::myExec(QString data)
{
QSqlQuery query(db);
query.exec(data);
bool isExec = query.exec();
if(isExec)
{
qDebug() << "Result: ";
while (query.next()) {
QString d = "----";
QSqlRecord q = query.record();
for(int i = 0;i < q.count();++i)
{
d += q.value(i).toString() + " ";
}
qDebug() << d;
}
qDebug() << "End";
return QSqlError();
}
qDebug() << "Data Error: " << query.lastError() << query.lastQuery();
return query.lastError();
}
使用热加载的组件LdLoader,qml如下
import QtQuick 2.0
import cpp 1.0
import QtQuick 2.12
import QtQuick.Layouts 1.12
import QtQuick.Controls 2.12
Item {
id: control
anchors.fill: parent
property string source
property var loader: loader
DropArea
{
id: dropArea
anchors.fill: parent
onEntered:
{
if(drag.hasText)
{
console.log(drag.text)
loader.source = drag.text + "?v=" + new Date().getTime()
}
}
onExited:
{
}
}
RowLayout
{
Layout.preferredHeight: parent.height
Layout.preferredWidth: parent.width
Loader
{
id:loader
Layout.preferredWidth: parent.width
Layout.preferredHeight: parent.height
onStatusChanged:
{
// if(status === Loader.Error)
// {
// MathUtil.trace(status)
// }
// else if(status === Loader.Loading)
// {
// sourceComponent = waitCom
// }
}
}
}
FileWatcher
{
id: fileWatcher
pathWatched: loader.source
onPathWatchedChanged:
{
console.log(path)
loader.source = ""
loader.source = "file://" + path + "?v=" + new Date().getTime().toString()
}
}
}
在主窗口中main.qml可以调用 LdLoader.qml和TestServer.qml
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
import cpp 1.0
Window {
id: window
visible: true
width: 640
height: 480
title: qsTr("Hello World")
LdLoader
{
id: ldLoader
anchors.fill: parent
Component.onCompleted:
{
ldLoader.loader.source = "file:///home/.../TestServer.qml" + "?v=" + new Date().getTime()
}
}
}
TestServer.qml部分代码如下
import QtQuick 2.0
import cpp 1.0
import QtQuick 2.12
import QtQuick.Layouts 1.12
import QtQuick.Controls 2.12
Item {
anchors.fill: parent
Connections{
target: server
onConnectedSql:{
server.runSql("select * from user")
}
}
LdServer
{
id: server
Component.onCompleted:
{
server.startServer(portTextField.text)
}
Component.onDestruction:
{
server.stopServer()
}
}
}
LdServer.cpp的部分代码如下:
namespace ld {
// 服务器端
class Server : public QObject
{
Q_OBJECT
public:
Server(QObject* p = nullptr);
~Server();
Q_INVOKABLE void startServer(uint32_t port= 12345)
{
if(dbManager==NULL)
{
dbManager = new ld::DatabaseManager(this);
connect(dbManager, &DatabaseManager::connectedSql, this, &Server::connectedSql);
dbManager->initdb();
}
if(server == NULL)
{
server = new QWebSocketServer("MyWebSocketServer", QWebSocketServer::NonSecureMode, this);
connect(server, &QWebSocketServer::newConnection, this, &Server::onNewConnection);
server->listen(QHostAddress::Any, port);
}
};
Q_INVOKABLE void stopServer();
Q_INVOKABLE void runSql(QString data){
if(dbManager && dbManager->db.isOpen())
{
dbManager->myExec(data);
}
if(dbManager && !dbManager->db.isOpen())
{
dbManager->initdb();
dbManager->myExec(data);
}
}
public slots:
void onNewConnection()
{
socket = server->nextPendingConnection();
...
connect(socket, &QWebSocket::textMessageReceived, this, &Server::onTextMessageReceived);
connect(socket, &QWebSocket::disconnected, this, &Server::onDisconnect);
};
void onTextMessageReceived(const QString &message);
void onDisconnect() {
QWebSocket* websocket = reinterpret_cast<QWebSocket*>(sender());
if(websocket)
{
...
websocket->deleteLater();
} };
signals:
...
void connectedSql();
private:
QWebSocketServer *server= NULL;
QTimer *timer= NULL;
QWebSocket *socket= NULL;
ld::DatabaseManager *dbManager = NULL;
QList<QWebSocket *> socketlist;
...
}
}
运行程序并修改TestServer.qml 里的数据时还是报第一个错误,但是可以查询到sql里的数据以及报错信息。