Qt对数据库的简单操作

1.问:数据库的操作一般是指什么?
答:我觉得任何一门语言对数据库的简单操作无非就是增、删、查、改等,入门一般都是使用SQL语句来操作数据库,当然使用SQL语句操作数据库的一大弊端就是,如果数据量大的话就会造成时间成本的剧增(如果使用单线程的话还会造成界面的卡死如果有界面的话);所以对于数据量大的存储,我觉得如果不使用多线程的话,尽量使用存储过程实现对数据库的操作。
2.问:Qt对数据库怎么操作?
答:这里只讲述简单的操作,所以我使用的也是SQL语句,而在项目中一般都会讲究mvc的思想,没有mvc的思想,自己写的代码两个月后来看只有一种感觉,我靠,这是谁写的代码,这么烂。而你自己也看不懂自己的代码,C++中类的出现使我们能够更好的管理我们的代码,写出复用性强,功能明确,分工也很明确的代码,因此,在这里,我也是将对数据库的操作封装成类,在以后使用的过程中,只是简单的copy几个文件的问题,再修改一下数据库表中的字段就很容易的实现了,节省大量的时间。
3.问:具体的实现?
答:先讲一下结构,我是将对数据库的操作单独封装成类,将读表和写表的过程再分别封装成类,这样就会很明确自己的步骤。并可以通过读配置文件的信息对数据库进行设置。看一下具体实现吧。
首先是对数据库设置名称,写代码写注释是一个很好的习惯,不要让别人看不懂你的代码。。

首先看看数据库表结构,我这里是操作了多张表


_rowid | FileName | FilePath | FileType | FileSize | FileTime |
1 | test.txt | C:\text | 文件 | 20 kb | 2106-12-17 10:21:56 |
2 | test.ini | D:\workspace\test | 文件 | 58 kb | 2106-12-17 10:21:56 |
3 | work | D:\workspace\test | 文件夹 | 0 kb | 2106-12-17 10:21:56 |


定义一些可以用到的变量

QSqlDatabase *pDb;
QSqlQuery *pQuery;
//连接名
QString connName;
//数据库文件
QString fileDb;
/*******************************************
 * creator      : @ji
 * function     : 设置数据库名称
 * Date         : 2016-09-13
 * parameter    : 数据库名称
********************************************/
bool QDBHelpe::setDBName(QString str_DBName)
{
    try{
        fileDb = str_DBName;
        return true;
    }
    catch(...)
    {
        return false;
    }
}

接下来解释千篇一律的打开数据库,关闭数据库等等。。

/*******************************************
 * creator      : @ji
 * function     : 打开数据库连接
 * Date         : 2016-09-13
 * parameter    :
********************************************/
int QDBHelpe::openDB()
{
    try
    {
        if (pDb)
        {
            closeDB();
        }
        pDb = new QSqlDatabase();
        //防止重复打开同名连接
        if(QSqlDatabase::contains(connName))
            *pDb = QSqlDatabase::database(connName);
        else
            *pDb = QSqlDatabase::addDatabase("QSQLITE", connName);
        pDb->setDatabaseName(fileDb);
        if (pDb->open())
        {
            if (pQuery)
            {
                delete pQuery;
                pQuery = NULL;
            }
            pQuery = new QSqlQuery(*pDb);
            return 0;
        }
        return -1;
    }
    catch (...)
    {
        return -1;
    }
}
/*******************************************
 * creator      : @ji
 * function     : 关闭数据库连接
 * Date         : 2016-09-13
 * parameter    : 串口信息
********************************************/
void QDBHelpe::closeDB()
{
    try
    {
        if (pQuery)
        {
            delete pQuery;
            pQuery = NULL;
        }
        if (pDb && pDb->isOpen())
        {
            pDb->close();
            delete pDb;
            pDb = NULL;
        }
        //从列表中移除连接
        QSqlDatabase::removeDatabase(connName);
    }
    catch (...) {}
}
/*******************************************
 * creator      : @ji
 * function     : 执行sql语句
 * Date         : 2016-09-13
 * parameter    : 需要执行的sql语句
********************************************/
bool QDBHelpe::executeSql(QString sql)
{
    try
    {
        openDB();
        QSqlQuery q(*pDb);
        bool ret = q.exec(sql);
        closeDB();
        qDebug()<<"ret = "<<ret<<"pDb";
        qDebug()<<"sql = "<<sql;
        return ret;
    }
    catch (...)
    {
        return false;
    }
}
/*******************************************
 * creator      : @ji
 * function     : 获取数据集
 * Date         : 2016-09-13
 * parameter    : sql语句     长度
********************************************/
QSqlQuery* QDBHelpe::getDataSet(QString sql,  int* pCount)
{
    try
    {
        openDB();
        qDebug()<<"sql = "<<sql;
        pQuery->exec(sql);
        if (!pCount)
            return pQuery;
        //获取记录数目
        if (pDb->driver()->hasFeature(QSqlDriver::QuerySize))
        {
            *pCount =  pQuery->size();
        }
        else
        {
            pQuery->last();
            *pCount = pQuery->at()+1;
            //回到第一条记录的前面
            pQuery->seek(-1);
        }
        return pQuery;
    }
    catch (...)
    {
        return NULL;
    }
}
/*******************************************
 * creator      : @ji
 * function     : 开始事物处理
 * Date         : 2016-09-13
 * parameter    :
********************************************/
void QDBHelpe::startTransaction()
{
    openDB();
    QSqlDatabase::database(connName).transaction();
}

/*******************************************
 * creator      : @ji
 * function     : 执行事物处理
 * Date         : 2016-09-13
 * parameter    : sql语句
********************************************/
void QDBHelpe::executeBatch(QString sql)
{
    pQuery->exec(sql);
}
/*******************************************
 * creator      : @ji
 * function     : 结束事物处理
 * Date         : 2016-09-13
 * parameter    : bool型值
********************************************/
void QDBHelpe::endTransaction(bool isOK)
{
    if (isOK)
        QSqlDatabase::database(connName).commit();
    else
        QSqlDatabase::database(connName).rollback();
    closeDB();
}

4.问:这只是对数据库的操作,对表的读写要怎么实现?
答:对表的读写我发现了一个很好用的东西,使用jsonobject类可以对表的字段进行序列化和反序列化,jsonobject类是在Qt5以后才出现的工具,以前在用Qt4的时候,也是很苦逼的在自己一行一行写SQL语句。对于表数据的读取详细见下:

/*****************sQLReadHelp.h****************************/
class sQLReadHelp
{
public:
    sQLReadHelp();
    void read(const QJsonObject &json);
    void write(QJsonObject &json) const;
    sQLReadHelp* getModel(QSqlQuery& query);
    virtual QList<sQLReadHelp*>* getFileList(QString strsql);
    virtual QList<sQLReadHelp*>* getList(QString strWhere,QString strTableName);   
public:
    QString m_FileName;
    QString m_FilePath;
    QString m_FileType;
    QString m_FileSize;
    QString m_FileTime;
};

上面定义的5个QString类型的字符串对应的就是表里面的字段,这些字段当然可以根据自己具体的表字段进行设置。

/*******************************************
 * creator      : @ji
 * function     : 反序列化
 * Date         : 2016-09-13
 * parameter    :
 *******************************************/
void sQLReadHelp::read(const QJsonObject &json)
{
    m_FileName  = json["FileName"].toString();
    m_FilePath  = json["FilePath"].toString();
    m_FileType  = json["FileType"].toString();
    m_FileSize  = json["FileSize"].toString();
    m_FileTime  = json["FileTime"].toString();
}
/*******************************************
 * creator      : @ji
 * function     : 序列化
 * Date         : 2016-09-13
 * parameter    :
 *******************************************/
void sQLReadHelp::write(QJsonObject &json) const
{
    json["FileName"]    = m_FileName;
    json["FilePath"]    = m_FilePath;
    json["FileType"]    = m_FileType;
    json["FileSize"]    = m_FileSize;
    json["FileTime"]    = m_FileTime;
}

反序列化和序列化就是将表中的字段值和QString字符串的相互转换。
读表的过程通常需要是将表里面的某一些数据全部读出来,所以我这里实现了获取表中的多行数据,单行数据的获取我没有实现,如果需要,可以自行实现。

/*******************************************
 * creator      : @ji
 * function     : 获取表单数据列表
 * Date         : 2016-09-13
 * parameter    : 数据库查询条件      数据库名
 *******************************************/
QList<sQLReadHelp*>* sQLReadHelp::getList(QString strWhere,QString strTableName)
{
    QSqlQuery* query = NULL;
    QList<sQLReadHelp*>* pCheckList = new QList<sQLReadHelp*>();
    if (strWhere.trimmed() != "")
    {
        strWhere = " where " + strWhere;
    }
    try
    {
        QString sql = QString("select * from %1 %2")
                      .arg(strTableName)
                      .arg(strWhere);
        int num = 0;
        query = g_pQDBHeper->getDataSet(sql, &num);
        for (int i=0; i < num; i++)
        {
            sQLReadHelp *pWrite = getModel(*query);
            if(pWrite != NULL)
            {
                pCheckList->append(pWrite);
            }
        }
        g_pQDBHeper->closeDB();
        return pCheckList;
    }
    catch(...)
    {
        if (query)
        {
            g_pQDBHeper->closeDB();
            query = NULL;
        }
        if (pCheckList)
        {
            //释放内部QcPlan指针
            qDeleteAll(*pCheckList);
            pCheckList->clear();
            delete pCheckList;
        }
    }
    return NULL;
}

而获取列表的前提是获取一行数据,

/*******************************************
 * creator      : @ji
 * function     : 获取一个对象实体
 * Date         : 2016-09-13
 * parameter    : 表单获取数据集指针
 *******************************************/
sQLReadHelp* sQLReadHelp::getModel(QSqlQuery& query)
{
    sQLReadHelp *pWrite = NULL;
    try
    {
        if (query.next())
        {
            pWrite = new sQLReadHelp();
            pWrite->m_FileName = query.value("FileName").toString();
            pWrite->m_FilePath = query.value("FilePath").toString();
            pWrite->m_FileType = query.value("FileType").toString();
            pWrite->m_FileSize = query.value("FileSize").toString();
            pWrite->m_FileTime = query.value("FileTime").toString();
            return pWrite;
        }
        return NULL;
    }
    catch(...)
    {
        if (pWrite)
            delete pWrite;
        return NULL;
    }
}

至此,对于表的读操作基本已经完成
5.问:那么写表呢?
答:写表和读表的过程基本是一样的,看看具体实现吧。

/**************************sQLWriteHelp.h*************************************/
class sQLWriteHelp
{
public:
    sQLWriteHelp();
    /**具体的函数会在cpp文件中讲到*/
public:
    /**这些字段对应表中的字段*/
    QString m_FileName;
    QString m_FilePath;
    QString m_FileType;
    QString m_FileSize;
    QString m_FileTime;
private:
    QString m_TableName;
};

序列化和反序列和读表的一模一样,这里就不在啰嗦了;获取更新表单和插入表单的SQL语句,说简单点就是一个重组SQL语句的过程。

/*******************************************
 * creator      : @ji
 * function     : 获取更新表单sql语句
 * Date         : 2016-09-13
 * parameter    : 数据类指针 sql查询条件
 *******************************************/
QString sQLWriteHelp::getUpdateStr(sQLWriteHelp* p, QString strWhere)
{
    QString sql = QString("update %1 set ").arg(m_TableName);

    sql += "FileName='" + p->m_FileName + "',";
    sql += "FilePath='" + p->m_FilePath + "',";
    sql += "FileType='" + p->m_FileType + "',";
    sql += "FileSize='" + p->m_FileSize + "',";
    sql += "FileTime='" + p->m_FileTime + "'";
    if (strWhere != "")
        sql += " where " + strWhere;
    else
        sql += " where FileName='" + p->m_FileName + "'";
    return sql;
}
/*******************************************
 * creator      : @ji
 * function     : 获取插入表单sql语句
 * Date         : 2016-09-13
 * parameter    : 数据类指针 sql查询条件
 *******************************************/
QString sQLWriteHelp::getInsertStr(sQLWriteHelp* p)
{
    QString sql = QString("insert into %1 (FileName,FilePath,FileType,FileSize,FileTime) values (")
                          .arg(m_TableName);
    sql += "'" + p->m_FileName + "',";
    sql += "'" + p->m_FilePath + "',";
    sql += "'" + p->m_FileType + "',";
    sql += "'" + p->m_FileSize + "',";
    sql += "'" + p->m_FileTime + "'";
    sql += ")";
    return sql;
}

判断表单是否存在某条记录,可以根据自己的需求选择是一个条件还是多个条件,我这里是因为同名文件可能存在于不同的文件夹,所以选择了判断两个字段。

/*******************************************
 * creator      : @ji
 * function     : 判断表单是否存在记录
 * Date         : 2016-09-13
 * parameter    : 查询条件
 *******************************************/
bool sQLWriteHelp::exist(QString strFileName,QString strFilePath)
{
    try
    {
        QString strSql = QString("select count(1) from %1 where FileName='%2' and FilePath='%3'")
                         .arg(m_TableName).arg(strFileName).arg(strFilePath);
        QSqlQuery *pQuery = g_pQDBHeper->getDataSet(C_STR(strSql), NULL);
        bool ret = false;
        if (pQuery->next())
        {
            ret = (pQuery->value(0).toInt() > 0) ? true : false;
        }
        g_pQDBHeper->closeDB();
        return ret;
    }
    catch (...)
    {
        return false;
    }
}

表单增加一个数据就是传入一个数据指针再解析的过程,然后插入数据库

/*******************************************
 * creator      : @ji
 * function     : 表单增加一条数据
 * Date         : 2016-09-13
 * parameter    : 数据类指针     表名称
 *******************************************/
bool sQLWriteHelp::add(sQLWriteHelp* model,QString strTableName)
{
    try
    {
        this->setTableName(strTableName);
        QString strwhere;
        strwhere = "";
        if (exist(model->m_FileName,model->m_FilePath))
        {
            update(model,strwhere);
            return true;
        }
        QString sql = getInsertStr(model);
        return g_pQDBHeper->executeSql(sql);
    }
    catch (...)
    {
        return false;
    }
}
/*******************************************
 * creator      : @ji
 * function     : 表单更新数据
 * Date         : 2016-09-13
 * parameter    : 数据类指针 sql查询条件
 *******************************************/
bool sQLWriteHelp::update(sQLWriteHelp* model, QString strWhere)
{
    try
    {
        QString sql = getUpdateStr(model,strWhere);
        return g_pQDBHeper->executeSql(sql);
    }
    catch(...)
    {
        return false;
    }
}

清空一张表,因为我这里表里面设置了第一列行号的自增功能,所以清空后需要将语气关联的记录该表行号的另一张表数据置0操作。

/*******************************************
 * creator      : @ji
 * function     : 清空一张表数据
 * Date         : 2016-12-08
 * parameter    : 表名称
 *******************************************/
bool sQLWriteHelp::deleteTableAllData(QString strTableName)
{
    QString sql = QString("delete from %1").arg(strTableName);
    g_pQDBHeper->executeSql(sql);
    QString sql2 = QString("update sqlite_sequence SET seq = 0 where name ='%1'").arg(strTableName);
    return g_pQDBHeper->executeSql(sql2);
}
/*******************************************
 * creator      : @ji
 * function     : 将一张表的数据完全覆盖另一张表
 * Date         : 2016-12-08
 * parameter    : 表名称
 *******************************************/
bool sQLWriteHelp::copyTB2ToTB1(QString strTableName1,QString strTableName2)
{
    QString sql = QString("insert into %1 select * from %2").arg(strTableName1).arg(strTableName2);
    return g_pQDBHeper->executeSql(sql);
}

6.问:封装好之后我们需要怎么具体的调用?
答:所以接下来我就要简单的讲讲具体的调用方法,首先看看插入数据

/**首先new一个写表的指针出来**/
sQLWriteHelp *model = new sQLWriteHelp();
/**接下来解释将数据赋值给指针的每一项**/
model->m_FileName = QString("生在90后的60后的专栏.ini");
model->m_FilePath = QSting("C:\xxx\xxx");
model->m_FileType = QString("文件"); 
model->m_FileSize = QString::number(520) + "kb";
model->m_FileTime = QString("2016-12-17");
/**调用插入标的函数就可以了**/
g_pSQLwriteHelp->add(model,m_strTableName);

从数据库获取列表

/********************************************************
 * creator      : @ji
 * function     : 从数据库中获取文件列表
 * Date         : 2016-12-08
 * parameter    :
 * ******************************************************/
QList<sQLReadHelp*>* FileSerch::getFileList(QString sql,QString strTableName)
{
    QList<sQLReadHelp*>* m_pCheckList;
    m_pCheckList = g_pSQLreadHelp->getList(sql,strTableName);
    return m_pCheckList;
}

至此,Qt对数据库的简单操作基本就已经完成了,欢迎大家交流学习,分享就是进步。。。

  • 6
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值