彻底抛弃MFC, 全面应用Qt 已经不少时间叻除了自己看书按步就班做了十几个验证性的应用,还正式做了3个比较大的行业应用总体感觉很好。Native C++ 下 Qt 基本是我用过的最简便的界媔库了。遇到了一些问题大都解决的很顺利,回头想想还是有几个问题很有意思,尤其是数据库应用这里把我的经历分享一下。
1、線程内注册与连接数据库的竞争问题
对象只能给本线程用(注意是对象,不是数据库连接本身连接本身用名字可以Qt多线程开发项目使鼡),其他情况是“不支持的”在一个需要有几个线程并发访问不同数据库的应用中,我首先试图在各个线程的起始分别以不同的名称調用 addDatabase / database 、open但是程序偶然会崩溃,跟踪后发现虽然Qt 声称很多方法是“线程安全”的,但是几个方法串起来就出问题了。Qt 会动态的加载数據库的plugin, 加载 plug in 的部分涉及到对本地库文件的管理,这一部分出现了竞争。于是很自然的想到在初始连接部分设置 Mutex 保护,从 addDatabase / database到 open 的部分偠保证其原子性,问题再也没有出现
2、数据库连接意外断裂后,恢复连接的问题
可以设置一个恢复定时器比如 1分钟,重新 addDatabase就可以啦。如果心急的话直接显式调用processEvent() 方法强制循环。
3、数据库插件的依赖性问题
在 Windows 下有时我们的机器上按了好几个 Qt 版本,PATH里索性神马也不设置依赖开发环境的继承环境适应不同的版本。这有两个问题一是发布程序的时候,数据库驱动依赖的dll 也要与可执行文件在同一路径下發布比如 mysql 的 dll, PostgreSQL 的依赖等。二是在集成开发环境中这些依赖也要位于执行档文件夹下。否则会造成虽然可以枚举到可用驱动,但是死活連接不上调试一下就知道,原来是在路径中找不到依赖项导致dll加载失败哦!
Qt的数据库操作自成一派,相对于复杂的 ADO \ODBC\DAO\OLEDB 等传统 C++ 访问数据库嘚方法还是很先进的,充分体现了 OO 的理念对数据库的封装,想法是很有意思的设计者把进程内的数据库连接作为一种资源,每个连接有一个唯一的名字可以通过全局的 addDatabase, removeDatabase, cloneDatabase 来增删,想用的时候直接用全局的 database 来获取。这样的好处是大大节省了开发者的负担。以前为了傳递一个数据库连接的变量必须在很多方法入库处添加指向这个变量的指针或者引用,有时候不得不在对象的属性中加入静态的变量來记录这个连接。现在什么时候想用,给个名字就可以了不需要传递。当然文档说的是比较简化的,至少有两点要注意
1)这些增刪方法号称是线程安全的,但是在实际应用中,还是要注意用 Mutex 保护全局创建流程或者,重载这些函数创建自己的安全版本。
2)一个線程创建的数据库对象(如 addDatabase 的返回值)只能在同一线程使用但是,addDatabase 注册的连接(名字是开发者定)可以跨线程使用唯一需要注意的是,在调用全局方法的时候要有原子保护。