【问题标题】:where should I declare a database object我应该在哪里声明一个数据库对象
【发布时间】:2013-04-04 10:16:10
【问题描述】:

我在 C++ 项目中使用 Qt 库,但我有一个设计问题:应该在哪里声明数据库?我宁愿不声明全局变量。

目前我正在以这种方式处理这个问题。我有一个主窗口,我已经在其中声明了数据库,因此我在主窗口中执行查询并使用不同的信号和插槽将结果传递给对话框。

我在主窗口启动时启动数据库,并在窗口关闭时关闭它。不知道这样行不行 现在我还需要另一个类中的数据库连接,这样我就可以传递对数据库的引用或使数据库全局化

我不喜欢这些解决方案.. 有处理这种情况的标准模式吗?

编辑:

我的班级现在看起来像:

class Database
{
  public:
    bool open(void);
    bool close(void);
    static Database* getDatabase(void);
    // various methods like loadThisTable(), saveThisTable() etc

  private:
    Database();                                // disable constructor
    ~Database();                               // disable destructor
    Database(const Database&);                 // disable copy constructor
    Database& operator=(const Database&);      // disable assignment

    static Database* instance_;                // database instance
    QSqlDatabase qtDB;                         // qt db database
}

如果我愿意,我可以添加添加和删除方法,但我只有一个数据库实例。

【问题讨论】:

  • 请澄清您所说的数据库对象是什么意思?你不是在用 QtSql 的模型类吗?
  • ps 我已经创建了一个类数据库,其方法如下:loadThis()、loadThat(),在这个类中有 qt 数据库,所以我不直接使用 qt 数据库。如果我使用它,我知道我可以使用 QSqlDatabase::addDatabase 添加数据库,然后使用 QSqlDatabase::database 从任何地方获取它
  • @SmitPatel 我为每个物理表创建了一个新类
  • 我认为对于模块化、易于阅读的代码,您的结构化方式很好。您可以在其他类中建立另一个连接。但如果你真的在考虑重用现有的连接,你应该看看shared pointer。这样您就可以在其他地方使用您的应用程序的现有连接。但这会使这项任务过于复杂。
  • 我知道 shared_pointer 但我没有考虑过。我会调查一下谢谢

标签: c++ database qt


【解决方案1】:

如果您使用QSqlDatabase,您实际上不需要将其设为全局变量。只需在首次启动应用程序时设置连接,然后在不同模块中需要时使用static QSqlDatabase 方法访问连接。

示例

QSqlDatabase db;  // set up the default connection
// alternative:  set up a named connection
// QSqlDatabase db("conn-name");

// set the connection params and open the connection

// ... later on
QSqlDatabase db = QSqlDatabase::database();  // retrieve the default connection
// alternative:  retrieve the named connection
// QSqlDatabase db = QSqlDatabase::database("conn-name");

来自the docs

QSqlDatabase 是一个值类。通过QSqlDatabase 的一个实例对数据库连接所做的更改将影响代表同一连接的QSqlDatabase 的其他实例。使用cloneDatabase() 在现有数据库的基础上创建一个独立的数据库连接。

注意:如果您的应用程序是多线程的,则必须小心只在创建它的线程中使用连接。

【讨论】:

    【解决方案2】:

    您需要一个singleton 模式。这是一个只有一个实例的全局类。有人称其为反模式(有时确实如此),但它是处理数据库连接等资源的最佳方式。

    别忘了您可以使用QSqlDatabase QSqlDatabase::database ( const QString & connectionName = QLatin1String( defaultConnection ), bool open = true ) [static] 方法通过名称获取QSqlDatabase 实例(名称可以通过QSqlDatabase QSqlDatabase::addDatabase ( QSqlDriver * driver, const QString & connectionName = QLatin1String( defaultConnection ) ) [static] 方法设置)以避免创建单例只是为了存储QSqlDatabase 实例。

    【讨论】:

    • “你需要一个单例模式”。不,绝对不是。没有人需要 单例,只有在您懒得寻找其他解决方案时才需要。 “这是处理数据库连接等资源的最佳方式”。谁说的?如果您想在应用程序中建立多个连接怎么办?
    • 圣战开始吧!好的,假设我有 2 个数据库连接需要在我的应用程序中使用。我应该将它们转移到我调用的每个表单或工人阶级,还是将它们存储在可以从任何地方访问的单例中?每个人都知道全局对象是不好的,但有时你只有数据库连接/工作线程池等全局资源,它们本质上是全局的。
    • “我应该将它们转移到我调用的每个表单或工人阶级,还是只将它们存储在可以从任何地方访问的单例中?”你能看到图案吗?如果你很懒,你会使用单例(但将来你会后悔),否则你会为每个类明确定义依赖关系,因此是的:你应该将它们转移到你调用的每个表单或工作类。这不是关于任何圣战,而是关于可重用性。如果您下次需要这些类中的任何一个来使用另一个数据库对象怎么办?
    • 全局并不是因为它们是全局的,而是因为其他对象硬编码了该特定全局实例的使用,而不是定义适当的可重用接口。
    • 你的论点很好,单例对代码重用、单元测试等非常不利。但有时当你不传输所有外部资源时,代码的可读性会更高-form-which-called-by-our-current-form 在我们表单的构造函数中使用。您可以观看 Qt 源代码以了解数据库连接如何存储在那里。单身人士是要避免的事情,但有时你只需要选择较少的邪恶。
    猜你喜欢
    • 2014-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-02
    • 2013-10-22
    • 1970-01-01
    • 2014-08-20
    相关资源
    最近更新 更多