Qt解析QSqlDatabase、QSqlQuery类操作数据库

时间:2023-01-22 10:50:35

1. Qt提供的对不同数据库的驱动支持:

Driver Type Description:
QDB2        IBM DB2
QIBASE     Borland InterBase Driver
QMYSQL  MySQL Driver
QOCI        Oracle Call Interface Driver
QODBC    ODBC Driver (includes Microsoft SQL Server)
QPSQL     PostgreSQL Driver
QSQLITE   SQLite version 3 or above
QSQLITE2 SQLite version 2
QTDS        Sybase Adaptive Server

2 .创建连接Oracle数据库实例:
  1. QSqlDatabase db = QSqlDatabase::addDatabase("QOCI", "OracleA");  
  2. db.setHostName("localhost");  //数据库主机名   
  3. db.setDatabaseName("scott");  //数据库名   
  4. db.setUserName("stott");      //数据库用户名   
  5. db.setPassword("tiger");      //数据库密码   
  6. db.open();          //打开数据库连接  
  7. db.close();         //释放数据库连接  
在使用 QSqlDatabase::addDatabase( "QOCI","OracleA" )函数时, 第一个参数是驱动类型主键,第二个是连接名。
//qsqldatabase.cpp文件
class QConnectionDict: public QHash<QString, QSqlDatabase>
{
public:
    inline bool contains_ts(const QString &key)
    {
        QReadLocker locker(&lock);
        return contains(key);
    }
    inline QStringList keys_ts() const
    {
        QReadLocker locker(&lock);
        return keys();
    }

    mutable QReadWriteLock lock;
};
Q_GLOBAL_STATIC(QConnectionDict, dbDict)
 
Qt定义了一个全局 QHash 容器用来存储这个进程里所有的数据库连接对象,存储格式QHash<连接名,QSqlDatabase >。
 
每次调用addDatabase接口都会检查这个容器里是否有这个连接,有的话断开之前的连接,建立现在加入的,没有直接 添加这个连接。
 
如果进程里涉及到操作多个不同数据库,则每个数据库的对象在添加连接时要区别开不一样的连接名,如果连接名相同,会使上一个已经建立的连接失效。
 
如果进程里多处地方(比如不同的线程)只连接到一个数据库,则需要把QSqlDatabase对象封装为全局对象(静态或者封装单例),所有的操作对象都使用这个数据库连接对象来进行操作。
 
(举例:进程中多个线程都建立了一个封装数据库操作的对象,他们都需要连接到一个数据库,所以单例就可以保证连接一次到处引用。如果想保持你线程里有一个独立的连接数据库操作对象,就需要调用addDatabase("device","connectName")连接名要不同于其他线程建立的,不然其他线程在操作数据库将无效)

 
3.使用QSqlQuery类操作数据库:
bool InsertData(cosnt Users &users)
{
  m_pqReportDB.transaction(); //使用数据库事务操作对下面批量插入性能会提高很多
  QSqlQuery sqlQuery(db); //使用已经打开成功的QSqlDatabase数据库对象驱动
  for(int i= 0; i <users.size(); i++)
  {
   sqlQuery.prepare("insert into tables(id, name) values(?,?)"); 
   sqlQuery.addBindValue(users[i].id); //还可以使用bindValue接口,参数绑定
   sqlQuery.addBindValue(users[i].name); 
   if (!sqlQuery.exec())
   {
     QSqlError error = sqlQuery.lastError();
     PQ_LOG_ERROR(error.text()); //记录错误日志
     m_pqReportDB.rollback(); //遇到错误,事务回滚
     return false;
   }
  }
  m_pqReportDB.commit();//提交事务,批量插入执行
  return true;
}