qt6 使用数据库(QSqlDatabase)工具链接 sqlite 时,第二次使用同名链接时,无法打开数据库?

问题描述:

存在如下代码:

/// <summary>
/// 创建一个 sqlite链接
/// </summary>
/// <param name="connectionName">链接名称</param>
/// <returns>链接</returns>
inline std::shared_ptr< QSqlDatabase > make_QSqlDatabase( const QString &connectionName ) {
	if( QSqlDatabase::contains( connectionName ) )
		return std::shared_ptr< QSqlDatabase >( new QSqlDatabase( QSqlDatabase::database( connectionName ) )
			, []( QSqlDatabase *p ) {
				if( p->isOpen( ) )
					p->close( );
				delete p;
			} );
	else
		return std::shared_ptr< QSqlDatabase >( new QSqlDatabase( QSqlDatabase::addDatabase( "QSQLITE", connectionName ) )
			, []( QSqlDatabase *p ) {
				if( p->isOpen( ) )
					p->close( );
				delete p;
			} );
}

已知它能为我们链接一个 “connectionName ”名称的数据库链接。

QSqlDatabase::addDatabase( "QSQLITE", connectionName ) 允许你基于驱动实现一个 sqlite 链接。

QSqlDatabase::database( connectionName ) 允许你重复链接一个已经存在的 “connectionName ”名称的数据库链接

现在,重复调用它。甚至释放

{
    auto dbLink = make_QSqlDatabase("234");
    dbLink->open(); // true
}
{
    auto dbLink = make_QSqlDatabase("234");
    dbLink->open(); // false
}

解决方案

使用 "QSqlDatabase::removeDatabase" 删除链接名称。

/// <summary>
/// 创建一个 sqlite链接
/// </summary>
/// <param name="connectionName">链接名称</param>
/// <returns>链接</returns>
inline std::shared_ptr< QSqlDatabase > make_QSqlDatabase( const QString &connectionName ) {
	static QMap< QString, size_t > userCount; // 保存链接次数,比要时候对其进行删除
	/// 释放处理调用
	auto releaseFunction = []( QSqlDatabase *p ) {
		QString connectionName = p->connectionName( );
		if( p->isOpen( ) ) {
			p->commit( );
			p->close( );
		}
		delete p;
		auto iterator = userCount.begin( );
		auto end = userCount.end( );
		for( ; iterator != end; ++iterator )
			if( iterator.key( ) == connectionName ) {
				size_t &value = iterator.value( );
				--value;
				if( value == 0 )
					QSqlDatabase::removeDatabase( connectionName );
				break;
			}
	};
	if( QSqlDatabase::contains( connectionName ) ) {
		++userCount[ connectionName ];
		return std::shared_ptr< QSqlDatabase >( new QSqlDatabase( QSqlDatabase::database( connectionName ) )
			, releaseFunction );
	} else {
		userCount.insert( connectionName, 1 );
		return std::shared_ptr< QSqlDatabase >( new QSqlDatabase( QSqlDatabase::addDatabase( "QSQLITE", connectionName ) )
			, releaseFunction );
	}

}

使用 QSqlDatabase::removeDatabase( connectionName ); 时,必须在数据库关闭之后,否则它会发生内存泄露!这是官方的提醒。这也说明,一个 QSqlDatabase 的关闭并不影响它被释放。

 官方正确案例

 {
     QSqlDatabase db = QSqlDatabase::database("sales");
     QSqlQuery query("SELECT NAME, DOB FROM EMPLOYEES", db);
 }
 // 在"db" 和 "query" 在堆栈已经释放
 QSqlDatabase::removeDatabase("sales"); // 正确的

  • 10
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值