【零基础学QT】【041】Qt操作数据库

使用ODBC
数据库种类繁多,由于版权原因,Qt并未包含某些数据库的驱动,比如MySQL,建议使用ODBC来取代特定数据库
ODBC,开放数据库连接,用于将不同的数据库操作转化为统一的操作接口,从而解决不同数据库之间的合作和迁移问题
以MySQL为例,我们只要安装对应的ODBC驱动( MySQL Connector ODBC),然后在操作系统中添加一个ODBC数据源,指向该数据库地址,之后我们就可以通过该ODBC数据源操作MySQL数据库
就算以后MySQL数据库更换为其它数据库,我们也只需要修改ODBC数据源即可,不需要修改代码
当然,在Qt中还有一个最大的好处,就是不用考虑不同的数据库驱动问题,由于没有自带所有主流数据库的驱动,有些驱动手动配置极其麻烦
在这里插入图片描述
表结构设计
本篇博客用到两个表,用户表(user)和角色表(role),用户表中的user_role通过外键引用角色表的role_id字段


	//角色表
	DROP TABLE IF EXISTS `role`;
	CREATE TABLE `role` (
	  `role_id` int(20) NOT NULL AUTO_INCREMENT,
	  `role_name` varchar(255) COLLATE utf8_bin NOT NULL DEFAULT '',
	  PRIMARY KEY (`role_id`)
	) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;


	//用户表
	DROP TABLE IF EXISTS `user`;
	CREATE TABLE `user` (
	  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
	  `user_id` varchar(255) COLLATE utf8_bin DEFAULT NULL,
	  `user_account` varchar(255) COLLATE utf8_bin DEFAULT NULL,
	  `user_password` varchar(255) COLLATE utf8_bin DEFAULT NULL,
	  `user_nickname` varchar(255) COLLATE utf8_bin DEFAULT NULL,
	  `user_realname` varchar(255) COLLATE utf8_bin DEFAULT NULL,
	  `org_id` varchar(255) COLLATE utf8_bin DEFAULT NULL,
	  `org_name` varchar(255) COLLATE utf8_bin DEFAULT NULL,
	  `dept_id` varchar(255) COLLATE utf8_bin DEFAULT NULL,
	  `dept_name` varchar(255) COLLATE utf8_bin DEFAULT NULL,
	  `user_role` int(20) NOT NULL,
	  PRIMARY KEY (`id`),
	  KEY `fk` (`user_role`),
	  CONSTRAINT `fk` FOREIGN KEY (`user_role`) REFERENCES `role` (`role_id`) ON DELETE CASCADE ON UPDATE CASCADE
	) ENGINE=InnoDB AUTO_INCREMENT=35 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

打开数据库


    //配置并打开数据库
    QSqlDatabase db = QSqlDatabase::addDatabase("QODBC");
    db.setHostName("localhost");
    db.setPort(3306);
    db.setDatabaseName("animal");
    db.setUserName("root");
    db.setPassword("123456");
    db.open();

查询数据
通过游标来迭代访问行数据,通过列索引或列名来遍历列数据


    //查询数据
    QSqlQuery query(db);
    query.exec("select * from user");
    while (query.next())
        qdebug << query.value("user_id") << query.value("user_name") << query.value(2) << query.value(3);
    QMessageBox::information(nullptr, "Info", "SQL Query Done");

插入数据


    //插入数据
    QSqlQuery query(db);
    query.prepare("INSERT INTO user (user_id, user_account) VALUES (?, ?)");
    query.addBindValue(QUuid::createUuid().toString());
    query.addBindValue(QUuid::createUuid().toString());
    query.exec();
    qdebug << query.numRowsAffected() << endl;
    qdebug << query.lastInsertId() << endl;
    qdebug << query.lastError() << endl;
    QMessageBox::information(nullptr, "Info", "SQL Insert Done");

修改数据


    //修改数据
    QSqlQuery query(db);
    query.prepare("UPDATE user SET user_password = ?, user_nickname = ? WHERE user_password is null");
    query.addBindValue(QUuid::createUuid().toString());
    query.addBindValue(QUuid::createUuid().toString());
    query.exec();
    qdebug << query.lastQuery() << endl;
    qdebug << query.numRowsAffected() << endl;
    QMessageBox::information(nullptr, "Info", "SQL Update Done");

删除数据


    //删除数据
    QSqlQuery query(db);
    query.exec("DELETE from user WHERE user_password is null");
    qdebug << query.numRowsAffected() << endl;
    QMessageBox::information(nullptr, "Info", "SQL Delete Done");

事务管理


    //事务管理
    db.transaction();
    try {
        // do something ...
        db.commit();
    } catch (...) {
        db.rollback();
    }

使用QSqlTableModel进行增删改查
QSqlTableModel对SQL功能进行了封装,以对象式编程风格取代SQL语法来操作数据库,可读写型更高
C++没有Java的反射功能,因此没法实现纯粹的对象式数据库框架,和SQL语法相比,优越性并不算非常大


    QSqlTableModel model(nullptr, db);

    //查询数据
    {
        model.setTable("user");
        model.setFilter(QObject::tr(" id is not null and id > %1 ").arg(10));
        model.select();
        qdebug << model.rowCount() << endl;
        for (int i = 0; i < model.rowCount(); i++) {
            QSqlRecord record = model.record(i);
            qdebug << record.value("id") << endl;
            qdebug << record.value("user_id") << endl;
            qdebug << record.value(2) << endl;
            qdebug << record.value(3) << endl;
        }
        model.clear();
    }

    //插入数据
    {
        model.setTable("user");
        QSqlRecord record = model.record();
        record.setValue("user_id", QUuid::createUuid().toString());
        record.setValue("user_account", QUuid::createUuid().toString());
        model.insertRecord(-1, record);  //-1表示在数据库末尾插入
        model.clear();
    }

    //修改数据
    //必须先查出记录,再修改提交
    {
        model.setEditStrategy(QSqlTableModel::OnManualSubmit);
        model.setTable("user");
        model.setFilter(" id = 10 ");
        model.select();
        for (int i = 0; i < model.rowCount(); i++)
            model.setData(model.index(i, 1), "update");  //1是列索引,表示修改哪一列
        model.submitAll();
        model.clear();
    }

    //删除数据
    //必须先查出记录,再删除提交
    {
        model.setTable("user");
        model.setFilter(" id > 10 ");
        model.select();
        model.removeRows(0, model.rowCount());
        model.submitAll();
        model.clear();
    }

TableView绑定SqlTableModel
QTableView可以绑定QSqlTableModel,直接显示数据库某个表格里面的数据


    QTableView w;
    w.show();

    //配置并打开数据库
    QSqlDatabase db = QSqlDatabase::addDatabase("QODBC");
    db.setHostName("localhost");
    db.setPort(3306);
    db.setDatabaseName("animal");
    db.setUserName("root");
    db.setPassword("123456");
    db.open();

    //查询数据
    QSqlTableModel model(nullptr, db);
    model.setTable("user");
    model.select();

    //TableView绑定SqlTableModel
    model.setHeaderData(0, Qt::Horizontal, "Data Id");
    model.setHeaderData(1, Qt::Horizontal, "User Id");
    model.setHeaderData(2, Qt::Horizontal, "User Account");
    model.setHeaderData(3, Qt::Horizontal, "User Password");
    model.setHeaderData(4, Qt::Horizontal, "User Realname");
    w.setModel(&model);
    w.resizeColumnsToContents();
    w.horizontalHeader()->setStretchLastSection(true);
    w.showMaximized();

利用SqlRelationalTableModel和DataWidgetMapper实现控件和数据库复杂关联
QDataWidgetMapper可以将数据库字段与某个控件关联
QSqlRelationalTableModel可以自动查询外键关联的其它表数据


    MainWindow w;
    w.show();

    //配置并打开数据库
    QSqlDatabase db = QSqlDatabase::addDatabase("QODBC");
    db.setHostName("localhost");
    db.setPort(3306);
    db.setDatabaseName("animal");
    db.setUserName("root");
    db.setPassword("123456");
    db.open();

    //主数据模型
    QSqlRelationalTableModel model(nullptr, db);
    model.setTable("user");
    model.setEditStrategy(QSqlTableModel::OnFieldChange);  //数值修改,焦点切换时,自动提交修改到数据库
    model.setRelation(model.fieldIndex("user_role"), QSqlRelation("role", "role_id", "role_name"));  //设置外键关联
    model.select();  //查询记录

    //关联数据模型
    //user_role已经被外键映射到role_name字段,要通过role_name来获得列索引
    int roleIndex = model.fieldIndex("role_name");
    QSqlTableModel* roleModel = model.relationModel(roleIndex);  //获取对应字段的所有可能值,给下拉框显示
    w.ui->userRoleNameCombo->setModel(roleModel);
    w.ui->userRoleNameCombo->setModelColumn(roleModel->fieldIndex("role_name"));

    //控件与字段绑定
    QDataWidgetMapper mapper;
    mapper.setSubmitPolicy(QDataWidgetMapper::AutoSubmit);  //下拉数值修改时,自动提交修改到数据库
    mapper.setModel(&model);  //关联数据模型
    mapper.setItemDelegate(new QSqlRelationalDelegate());
    mapper.addMapping(w.ui->userIdEdit, model.fieldIndex("id"));  //将数据映射到控件
    mapper.addMapping(w.ui->userAccountEdit, model.fieldIndex("user_account"));
    mapper.addMapping(w.ui->userRealnameEdit, model.fieldIndex("user_realname"));
    mapper.addMapping(w.ui->userRoleNameCombo, model.fieldIndex("user_role"));
    mapper.toFirst();  //显示首个记录
    mapper.toNext();

发布了442 篇原创文章 · 获赞 45 · 访问量 15万+

猜你喜欢

转载自blog.csdn.net/u013718730/article/details/103617666