用于同步数据库访问的类

时间:2015-02-17 16:05:14

标签: c++ database multithreading qt design-patterns

我有一个单例类,用于管理来自多个线程的数据库访问。该课程必须符合以下要求:

  1. 可以同时进行读取操作,但写入必须是独占的(没有其他写入或读取)。
  2. 单个连接应该重复用于多个查询(在一个线程中)。
  3. 每个线程都需要拥有自己与数据库的连接。
  4. 接口不应泄露实现细节,只暴露对资源的访问(因此客户端不知道它是否与数据库,文件或内存一起使用)
  5. 我当前的解决方案使用QReadWriteLock来处理同步,但是所有线程都使用单个数据库连接,这是不安全的。以下是简化版。

    class ResourceManager
    {
    public:
        bool initialize(const QString& databasePath);
        bool shutdown();
    
        static ResourceManager& get()
        {
            static ResourceManager instance;
            return instance;
        }
    
        QByteArray getResource(int resourceId)
        {
            QReadLocker locker(m_lock);
            QSqlQuery query(m_db);
            // ...
        }
    
        bool setResource(int resourceId, QByteArray data)
        {
            QWriteLocker locker(m_lock);
            QSqlQuery query(m_db)
            // ...
        }
    
    private:
        QSqlDatabase m_db;
        QReadWriteLock m_lock;
    }
    

    我的想法是实现某种连接缓存,如下所示:

    QHash<ThreadHandle, QString> m_connectionCache; // thread handle - connection name
    
    // then
    if (!m_connectionCache[QThread::currentThread]) // Create new connection
    QSqlQuery query(m_connectionCache[QThread::currentThread]);
    

    这里的问题是我无法想象一个好的清理机制可以摆脱不再需要的连接,因此地图将随着每个新线程不断成长。

    这看起来是个好主意吗?还有其他建议吗?

1 个答案:

答案 0 :(得分:0)

可以通过名称访问连接,但是您将QString传递给QSqlQuery的构造函数,此字符串被视为SQL查询,但不是连接名。

幸运的是QSqlDatabase包含您需要的缓存。可以通过QSqlDatabase::connectionNames阅读并按QSqlDatabase::addDatabase

撰写