QSqlDatabase的进一步封装(多线程支持+更加简单的操作)——同时支持MySQL, SQL Server和Sqlite

时间:2022-12-25 23:37:09

开发背景:

1.直接用QSqlDatabase我觉得太麻烦了;

2.对于某些数据库,多个线程同时使用一个QSqlDatabase的时候会崩溃;

3.这段时间没什么干货放出来觉得浑身不舒服,就想写一个。

于是,我就封装了一下

只要简单的实例化,然后通过query()就可以拿到QSqlQuery的实例化对象。

还自带计时,一段时间不用可自动关闭,既保证效率也不占用无用资源。

注:需要C++11的支持

不多说,上代码:

JasonQt_Database.h

  1. #ifndef __JasonQt_Database_h__
  2. #define __JasonQt_Database_h__
  3. // C++ lib import
  4. #include <functional>
  5. // Qt lib import
  6. #include <QtCore>
  7. #include <QtSql>
  8. #define PropertyDeclare(Type, Name, setName, ...)                   \
  9. private:                                                        \
  10. Type m_ ## Name __VA_ARGS__;                                    \
  11. public:                                                         \
  12. inline const Type &Name(void) const { return m_ ## Name; }      \
  13. inline void setName(const Type &Name) { m_ ## Name = Name; }    \
  14. private:
  15. namespace JasonQt_Database
  16. {
  17. enum DatabaseModeEnum{ DatabaseNameMode, DatabaseHostMode };
  18. enum QueryMode { QueryAutoMode, QueryMultiMode, QuerySingleMode };
  19. class DatabaseSettings
  20. {
  21. private:
  22. PropertyDeclare(DatabaseModeEnum, databaseMode, setDatabaseMode)
  23. PropertyDeclare(QString, databaseType, setDatabaseType)
  24. PropertyDeclare(QString, connectionName, setConnectionName)
  25. // File mode
  26. PropertyDeclare(QString, nameModeName, setNameModeName)
  27. // Host mode
  28. PropertyDeclare(QString, hostModeHostName, setHostModeHostName)
  29. PropertyDeclare(QString, hostModeDatabaseName, setHostModeDatabaseName)
  30. PropertyDeclare(QString, hostModeUserName, setHostModeUserName)
  31. PropertyDeclare(QString, hostModePassword, setHostModePassword)
  32. private:
  33. DatabaseSettings(const DatabaseModeEnum &databastMode, const QString &databaseType, const QString &connectionName);
  34. public:
  35. DatabaseSettings(const QString &databaseType, const QString &connectionName, const QString &nameModeName);
  36. DatabaseSettings(const QString &databaseType, const QString &connectionName, const QString &hostModeHostName, const QString &hostModeDatabaseName, const QString &hostModeUserName, const QString &hostModePassword);
  37. };
  38. class ConnectSettings
  39. {
  40. private:
  41. PropertyDeclare(int, maxOpenTime, setMaxOpenTime)
  42. PropertyDeclare(QueryMode, queryMode, setQueryMode)
  43. PropertyDeclare(int, minWaitTime, setMinWaitTime)
  44. public:
  45. ConnectSettings(const int &maxOpenTime = 60 * 1000, const QueryMode &queryMode = QueryAutoMode, const int &minWaitTime = -1);
  46. };
  47. class Query
  48. {
  49. private:
  50. QSqlQuery *m_query;
  51. QMutex *m_mutex = NULL;
  52. public:
  53. Query(QSqlDatabase &dataBase, QMutex *mutex = NULL);
  54. Query(Query &&other);
  55. ~Query(void);
  56. inline QSqlQuery *operator->(void) { return m_query; }
  57. inline QSqlQuery *operator*(void) { return m_query; }
  58. QSqlQuery *takeQuery(void);
  59. QMutex *takeMutex(void);
  60. };
  61. class ConnectNode: public QObject
  62. {
  63. Q_OBJECT
  64. private:
  65. QSqlDatabase *m_database = NULL;
  66. QString m_connectionName;
  67. DatabaseSettings m_dataBaseSettings;
  68. ConnectSettings m_connectSettings;
  69. QTimer *m_autoClose = NULL;
  70. QMutex *m_mutex = NULL;
  71. public:
  72. ConnectNode(const DatabaseSettings &dataBaseSettings, const ConnectSettings &connectSettings);
  73. ~ConnectNode(void);
  74. public:
  75. Query query(void);
  76. public slots:
  77. bool addDataBase(void);
  78. void removeDataBase(void);
  79. bool open(void);
  80. void close(void);
  81. signals:
  82. void controlStartAutoClose(void);
  83. void controlStopAutoClose(void);
  84. };
  85. class Control
  86. {
  87. private:
  88. DatabaseSettings m_databaseSettings;
  89. ConnectSettings m_connectSettings;
  90. QMap<qint64, ConnectNode *> m_node;
  91. QMutex m_mutex;
  92. QTime *m_wait = NULL;
  93. public:
  94. Control(const DatabaseSettings &databaseSettings, const ConnectSettings &connectSettings = ConnectSettings());
  95. Control(const Control &) = delete;
  96. ~Control(void);
  97. public:
  98. void removeAll(void);
  99. Query query(void);
  100. private:
  101. void insert(const qint64 &key);
  102. };
  103. }
  104. #endif//__JasonQt_Database_h__

JasonQt_Database.cpp

  1. #include "JasonQt_Database.h"
  2. using namespace JasonQt_Database;
  3. // DatabaseSettings
  4. DatabaseSettings::DatabaseSettings(const DatabaseModeEnum &databastMode, const QString &databaseType, const QString &connectionName)
  5. {
  6. m_databaseMode = databastMode;
  7. m_databaseType = databaseType;
  8. m_connectionName = connectionName;
  9. }
  10. DatabaseSettings::DatabaseSettings(const QString &databaseType, const QString &connectionName, const QString &nameModeName):
  11. DatabaseSettings(DatabaseNameMode, databaseType, connectionName)
  12. {
  13. m_nameModeName = nameModeName;
  14. }
  15. DatabaseSettings::DatabaseSettings(const QString &databaseType, const QString &connectionName, const QString &hostModeHostName, const QString &hostModeDatabaseName, const QString &hostModeUserName, const QString &hostModePassword):
  16. DatabaseSettings(DatabaseHostMode, databaseType, connectionName)
  17. {
  18. m_hostModeHostName = hostModeHostName;
  19. m_hostModeDatabaseName = hostModeDatabaseName;
  20. m_hostModeUserName = hostModeUserName;
  21. m_hostModePassword = hostModePassword;
  22. }
  23. // ConnectSettings
  24. ConnectSettings::ConnectSettings(const int &maxOpenTime, const QueryMode &queryMode, const int &minWaitTime)
  25. {
  26. m_maxOpenTime = maxOpenTime;
  27. m_queryMode = queryMode;
  28. m_minWaitTime = minWaitTime;
  29. }
  30. // Query
  31. Query::Query(QSqlDatabase &dataBase, QMutex *mutex):
  32. m_query(new QSqlQuery(dataBase))
  33. {
  34. m_mutex = mutex;
  35. }
  36. Query::Query(Query &&other)
  37. {
  38. m_query = other.takeQuery();
  39. m_mutex = other.takeMutex();
  40. }
  41. Query::~Query(void)
  42. {
  43. if(m_query)
  44. {
  45. delete m_query;
  46. }
  47. if(m_mutex)
  48. {
  49. m_mutex->unlock();
  50. }
  51. }
  52. QSqlQuery *Query::takeQuery(void)
  53. {
  54. auto buf = m_query;
  55. m_query = NULL;
  56. return buf;
  57. }
  58. QMutex *Query::takeMutex(void)
  59. {
  60. auto buf = m_mutex;
  61. m_mutex = NULL;
  62. return buf;
  63. }
  64. // ConnectNode
  65. ConnectNode::ConnectNode(const DatabaseSettings &dataBaseSettings, const ConnectSettings &connectSettings):
  66. m_dataBaseSettings(dataBaseSettings),
  67. m_connectSettings(connectSettings)
  68. {
  69. m_connectionName = QString("%1(%2)").arg(m_dataBaseSettings.connectionName()).arg(QString::number(qint64(QThread::currentThread()), 16));
  70. m_mutex = new QMutex(QMutex::Recursive);
  71. if(m_connectSettings.maxOpenTime())
  72. {
  73. m_autoClose = new QTimer;
  74. m_autoClose->setSingleShot(true);
  75. m_autoClose->setInterval(m_connectSettings.maxOpenTime());
  76. m_autoClose->moveToThread(qApp->thread());
  77. m_autoClose->setParent(qApp);
  78. connect(m_autoClose, SIGNAL(timeout()), this, SLOT(close()), Qt::DirectConnection);
  79. connect(this, SIGNAL(controlStartAutoClose()), m_autoClose, SLOT(start()));
  80. connect(this, SIGNAL(controlStopAutoClose()), m_autoClose, SLOT(stop()));
  81. }
  82. this->addDataBase();
  83. }
  84. ConnectNode::~ConnectNode(void)
  85. {
  86. if(m_mutex){ m_mutex->lock(); }
  87. if(m_autoClose)
  88. {
  89. m_autoClose->deleteLater();
  90. }
  91. this->removeDataBase();
  92. if(m_mutex){ m_mutex->unlock(); }
  93. if(m_mutex){ delete m_mutex; }
  94. }
  95. Query ConnectNode::query(void)
  96. {
  97. if(!m_database)
  98. {
  99. this->addDataBase();
  100. }
  101. if(!m_database->isOpen())
  102. {
  103. m_database->open();
  104. }
  105. if(m_mutex){ m_mutex->lock(); }
  106. Query buf(*m_database, m_mutex);
  107. emit controlStartAutoClose();
  108. return buf;
  109. }
  110. bool ConnectNode::addDataBase(void)
  111. {
  112. if(m_mutex){ m_mutex->lock(); }
  113. if(m_database)
  114. {
  115. this->removeDataBase();
  116. }
  117. m_database = new QSqlDatabase(QSqlDatabase::addDatabase(m_dataBaseSettings.databaseType(), m_connectionName));
  118. switch(m_dataBaseSettings.databaseMode())
  119. {
  120. case DatabaseNameMode:
  121. {
  122. m_database->setDatabaseName(m_dataBaseSettings.nameModeName());
  123. break;
  124. }
  125. case DatabaseHostMode:
  126. {
  127. m_database->setHostName(m_dataBaseSettings.hostModeHostName());
  128. m_database->setDatabaseName(m_dataBaseSettings.hostModeDatabaseName());
  129. m_database->setUserName(m_dataBaseSettings.hostModeUserName());
  130. m_database->setPassword(m_dataBaseSettings.hostModePassword());
  131. break;
  132. }
  133. default:
  134. {
  135. if(m_mutex){ m_mutex->unlock(); }
  136. return false;
  137. }
  138. }
  139. const auto &&flag = this->open();
  140. if(m_mutex){ m_mutex->unlock(); }
  141. return flag;
  142. }
  143. void ConnectNode::removeDataBase(void)
  144. {
  145. if(m_mutex){ m_mutex->lock(); }
  146. delete m_database;
  147. m_database = NULL;
  148. QSqlDatabase::removeDatabase(m_connectionName);
  149. if(m_mutex){ m_mutex->unlock(); }
  150. }
  151. bool ConnectNode::open(void)
  152. {
  153. if(!m_database)
  154. {
  155. this->addDataBase();
  156. }
  157. if(m_mutex){ m_mutex->lock(); }
  158. emit controlStartAutoClose();
  159. const auto &&Flag = m_database->open();
  160. if(m_mutex){ m_mutex->unlock(); }
  161. return Flag;
  162. }
  163. void ConnectNode::close(void)
  164. {
  165. if(m_mutex)
  166. {
  167. if(m_mutex->tryLock())
  168. {
  169. m_mutex->unlock();
  170. emit controlStopAutoClose();
  171. m_database->close();
  172. }
  173. else
  174. {
  175. emit controlStartAutoClose();
  176. }
  177. }
  178. else
  179. {
  180. emit controlStopAutoClose();
  181. m_database->close();
  182. }
  183. }
  184. // Control
  185. Control::Control(const DatabaseSettings &databaseSettings, const ConnectSettings &connectSettings):
  186. m_databaseSettings(databaseSettings),
  187. m_connectSettings(connectSettings)
  188. {
  189. if(m_connectSettings.queryMode() == QueryAutoMode)
  190. {
  191. if(databaseSettings.databaseType() == "QMYSQL")
  192. {
  193. m_connectSettings.setQueryMode(QueryMultiMode);
  194. }
  195. else if(databaseSettings.databaseType() == "QODBC")
  196. {
  197. m_connectSettings.setQueryMode(QueryMultiMode);
  198. }
  199. else
  200. {
  201. m_connectSettings.setQueryMode(QuerySingleMode);
  202. }
  203. }
  204. if(m_connectSettings.queryMode() == QuerySingleMode)
  205. {
  206. this->insert(qint64(QThread::currentThread()));
  207. }
  208. if(m_connectSettings.minWaitTime() == -1)
  209. {
  210. if(databaseSettings.databaseType() == "QMYSQL")
  211. {
  212. m_connectSettings.setMinWaitTime(0);
  213. }
  214. else if(databaseSettings.databaseType() == "QODBC")
  215. {
  216. m_connectSettings.setMinWaitTime(0);
  217. }
  218. else
  219. {
  220. m_connectSettings.setMinWaitTime(5);
  221. m_wait = new QTime;
  222. m_wait->start();
  223. }
  224. }
  225. else
  226. {
  227. m_wait = new QTime;
  228. m_wait->start();
  229. }
  230. }
  231. Control::~Control(void)
  232. {
  233. for(auto &now: m_node)
  234. {
  235. now->deleteLater();
  236. }
  237. if(m_wait)
  238. {
  239. delete m_wait;
  240. }
  241. }
  242. void Control::removeAll(void)
  243. {
  244. m_mutex.lock();
  245. for(auto &Now: m_node)
  246. {
  247. Now->removeDataBase();
  248. }
  249. m_mutex.unlock();
  250. }
  251. Query Control::query(void)
  252. {
  253. if(m_wait)
  254. {
  255. const auto &&flag = m_connectSettings.minWaitTime() - m_wait->elapsed();
  256. m_wait->restart();
  257. if(flag > 0)
  258. {
  259. QThread::msleep(flag);
  260. }
  261. }
  262. if(m_connectSettings.queryMode() == QueryMultiMode)
  263. {
  264. m_mutex.lock();
  265. const auto &¤tThread = qint64(QThread::currentThread());
  266. const auto &&now = m_node.find(currentThread);
  267. if(now != m_node.end())
  268. {
  269. auto buf((*now)->query());
  270. m_mutex.unlock();
  271. return buf;
  272. }
  273. else
  274. {
  275. this->insert(qint64(QThread::currentThread()));
  276. m_mutex.unlock();
  277. return this->query();
  278. }
  279. }
  280. else
  281. {
  282. return (*m_node.begin())->query();
  283. }
  284. }
  285. void Control::insert(const qint64 &key)
  286. {
  287. m_node[key] = new ConnectNode(m_databaseSettings, m_connectSettings);
  288. }

使用:

  1. // Qt lib import
  2. #include <QCoreApplication>
  3. #include <QtConcurrent>
  4. #include <QSqlError>
  5. // JasonQt lib import
  6. #include "JasonQt/JasonQt_Database.h"
  7. int main(int argc, char *argv[])
  8. {
  9. QCoreApplication a(argc, argv);
  10. /*
  11. * 注:关于附加参数
  12. * 这是可以不写的,如果要写的话,可以参考这个:
  13. *
  14. * 单次打开数据库最大时间:也就是最大open的时间,对于某些数据库,长时间open但不使用,不仅会造成资源浪费还会意外断开。在设置了60 * 1000后,且60秒内未进行查询,就自动断开。
  15. * 多线程支持:简单的说就是高级点的数据库,比如 MySql 写 JasonQt_Database::QueryMultiMode ;低级的,比如 Sqlite ,写 JasonQt_Database::QuerySingleMode ,就可以了。
  16. * 最小等待时间:对于某些数据库,比如Sqlite,密集查询时可能出错,此时可以适当的提升两次查询之间的最小等待时间,比如10ms
  17. */
  18. // Sqlite的连接方式                    类型        连接名        Sqlite文件路径      单次打开数据库最大时间                多线程支持           最小等待时间
  19. JasonQt_Database::Control control({ "QSQLITE", "TestDB", "/Users/Jason/test.db" }, { 60 * 1000,        JasonQt_Database::QuerySingleMode, 10});
  20. // MySql的连接方式                      类型      连接名        IP        数据库    用户名        密码
  21. //  JasonQt_Database::Control control({ "QMYSQL", "TestDB", "localhost", "JasonDB", "root", "YourPassword" });
  22. // SqlServer的连接方式                  类型      连接名                                    数据库              数据库名   用户名         密码
  23. //  JasonQt_Database::Control control({ "QODBC", "TestDB", "Driver={SQL SERVER};server=iZ23kn6vmZ\\TEST;database=test;uid=sa;pwd=YourPassword;" });
  24. auto insert = [&]()
  25. {
  26. auto query(control.query()); // 这里的query在解引用( -> 或者 * )后返回的是 QSqlQuery ,直接用就可以了,不需要单独打开数据库或者其他的初始化
  27. query->prepare("insert into Test1 values(?)"); // 模拟插入操作
  28. query->addBindValue(rand() % 1280);
  29. if(!query->exec())
  30. {
  31. qDebug() << "Error" << __LINE__;
  32. }
  33. query->clear();
  34. query->prepare("insert into Test2 values(NULL, ?, ?)");
  35. query->addBindValue(rand() % 1280);
  36. QString buf;
  37. for(int now = 0; now < 50; now++)
  38. {
  39. buf.append('a' + (rand() % 26));
  40. }
  41. query->addBindValue(buf);
  42. if(!query->exec())
  43. {
  44. qDebug() << "Error" << __LINE__;
  45. }
  46. };
  47. auto delete_ = [&]()
  48. {
  49. auto query(control.query());
  50. query->prepare("delete from Test1 where data = ?");
  51. query->addBindValue(rand() % 1280);
  52. if(!query->exec())
  53. {
  54. qDebug() << "Error" << __LINE__;
  55. }
  56. query->clear();
  57. query->prepare("delete from Test2 where data1 = ?");
  58. query->addBindValue(rand() % 1280);
  59. if(!query->exec())
  60. {
  61. qDebug() << "Error" << __LINE__;
  62. }
  63. };
  64. auto update = [&]()
  65. {
  66. auto query(control.query());
  67. query->prepare("update Test1 set data = ? where data = ?");
  68. query->addBindValue(rand() % 1280);
  69. query->addBindValue(rand() % 1280);
  70. if(!query->exec())
  71. {
  72. qDebug() << "Error" << __LINE__;
  73. }
  74. query->clear();
  75. query->prepare("update Test2 set data1 = ?, data2 = ? where data1 = ?");
  76. query->addBindValue(rand() % 1280 + 1);
  77. QString buf;
  78. for(int now = 0; now < 50; now++)
  79. {
  80. buf.append('a' + (rand() % 26));
  81. }
  82. query->addBindValue(buf);
  83. query->addBindValue(rand() % 1280 + 1);
  84. if(!query->exec())
  85. {
  86. qDebug() << "Error" << __LINE__;
  87. }
  88. };
  89. auto select = [&]()
  90. {
  91. auto query(control.query());
  92. query->prepare("select * from Test1 where data = ?");
  93. query->addBindValue(rand() % 1280);
  94. if(!query->exec())
  95. {
  96. qDebug() << "Error" << __LINE__;
  97. }
  98. query->clear();
  99. query->prepare("select * from Test2 where data1 = ?");
  100. query->addBindValue(rand() % 1280);
  101. if(!query->exec())
  102. {
  103. qDebug() << "Error" << __LINE__;
  104. }
  105. };
  106. volatile int count = 0, last = 0;
  107. QTime time;
  108. time.start();
  109. QThreadPool::globalInstance()->setMaxThreadCount(10);
  110. for(int now = 0; now < 3; now++) // 开启3个线程测试
  111. {
  112. QtConcurrent::run([&]()
  113. {
  114. while(true)
  115. {
  116. count++;
  117. if(!(count % 1000))
  118. {
  119. const auto &&now = time.elapsed();
  120. qDebug() << now - last; // 打印每完成1000语句的时间
  121. last = now;
  122. }
  123. switch(rand() % 20)
  124. {
  125. case 0:  { insert(); break; }
  126. case 1:  { delete_(); break; }
  127. case 2:  { update(); break; }
  128. default: { select(); break; }
  129. }
  130. }
  131. QThread::msleep(10);
  132. });
  133. }
  134. return a.exec();
  135. }

我也写了一个示例工程,可以前往这里下载

http://download.csdn.net/detail/wsj18808050/8566497

http://blog.csdn.net/wsj18808050/article/details/44891715

QSqlDatabase的进一步封装(多线程支持+更加简单的操作)——同时支持MySQL, SQL Server和Sqlite的更多相关文章

  1. 功能齐全、效率一流的免费开源数据库导入导出工具(c&num;开发,支持SQL server、SQLite、ACCESS三种数据库),每月借此处理数据5G以上

    软件名:DataPie 功能:支持SQL server.SQLite.ACCESS数据库的导入.导出.存储过程调用,支持EXCEL2007.EXCEL2003.ACCESS2007. CSV文件导入数 ...

  2. 查询获取所有数据库名及数据库中表的集合、数据库连接字符串(类生成器,暂时支持mysql&comma;sql server,后期有oracle再更新)

    现所在公司做项目开发时,经常会自己创建model类,网上的生成器也很多,完全满足自己的不太现实,所以感觉自己做一个更有底气,主要针对过程中的一些语句进行整理,也供其他人学习参考. 连接字符串: mys ...

  3. 最简单 无返回值 无参数 sql server存储过程

    CREATE proc Upadte_stateas update Table_1 set [state]=2 where id in (select id from Table_1 where st ...

  4. SQL Server 2016原生支持JSON

    转载原地址: http://www.cnblogs.com/lyhabc/p/4747694.html SQL Server 2005 开始支持 XML 数据类型,提供原生的 XML数据类型.XML ...

  5. 自动化安装SQL Server&plus;SP就那么简单

    随着业务.企业规模的日益壮大,DB的数量也在不断增多,配置一台新增DB,从服务器的参数配置,磁盘阵列规划,DB安装部署,DB参数调优等等一列步骤下来,手工操作的效率变得越来越低,因为我负责的数据库近些 ...

  6. 动化安装SQL Server&plus;SP就那么简单

    随着业务.企业规模的日益壮大,DB的数量也在不断增多,配置一台新增DB,从服务器的参数配置,磁盘阵列规划,DB安装部署,DB参数调优等等一列步骤下来,手工操作的效率变得越来越低,因为我负责的数据库近些 ...

  7. Microsoft SQL Server JDBC 驱动程序支持矩阵

    本页包含 Microsoft SQL Server JDBC 驱动程序的支持矩阵和支持生命周期策略. Microsoft JDBC 驱动程序支持生命周期矩阵和策略 Microsoft 支持生命周期 ( ...

  8. YxdJSON - Delphi 高性能 JSON 库(支持RTTI和序列化操作)

    源:YxdJSON - Delphi 高性能 JSON 库(支持RTTI和序列化操作) Delphi 高性能 JSON 库(支持RTTI和序列化操作) 支持平台: Windows, Android, ...

  9. SQL Server On Linux:基于实际项目案例,总结功能支持情况及相关问题解决方案,讲如何快速完成迁移

    上个月,有个朋友问我说Sql Sever向Mysql迁移有什么好的经验分享,他们公司客户明确提出不再提供Windows服务器,现在计划Mysql迁移.我说Mysql迁移成本太高了,不妨可以了解一下SQ ...

随机推荐

  1. Windows 历史

  2. 多线程程序设计学习(8)Thread-Per-Message

    Thread-Per-Message[这个工作交给你模式]一:Thread-Per-Message的参与者--->Client(委托人)--->host(中介开线程)--->hepl ...

  3. Android 网络编程与通信协议

    大多数的Android应用程序都会使用HTTP协议来发送和接收网络数据,而Android中主要提供了两种方式来进行HTTP操作, HttpURLConnection和HttpClient.这两种方式都 ...

  4. 论如何进CSDN博客排名前500

    http://www.jtahstu.com/blog/post-71.html 目前该方法并不适用于博客园,显然写博客园的程序员智商要高些.

  5. HDU 5763 Another Meaning(FFT)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5763 [题目大意] 给出两个串S和T,可以将S串中出现的T替换为*,问S串有几种表达方式. [题解 ...

  6. 【批处理学习笔记】第十一课:常用DOS命令(1)

    [ 文件夹管理 ]cd 显示当前目录名或改变当前目录.md 创建目录.rd 删除一个目录.dir 显示目录中的文件和子目录列表.tree 以图形显示驱动器或路径的文件夹结构.path 为可执行文件显示 ...

  7. Microsoft Dynamics CRM 2011 JS操作集锦

    1.Xrm.Page.context 用户ID:getUserId() 用户角色:getUserRoles() 用户语言:getUserLcid() 组织名称:getOrgUniqueName() 组 ...

  8. ECMA Script 6&lowbar;字符串&lowbar;扩展&lowbar;字符 是4字节还是2字节?&lowbar;模板字符串

    ES6 字符串扩展 ES6 加强了对 Unicode 的支持,并且扩展了字符串对象 字符 的 Unicode 表示法 允许采用 \uxxxx 形式表示一个字符, 其中 xxxx 表示字符的 Unico ...

  9. Sublime Text3 调色板 ColorPicker插件安装及快捷键

    一.安装 第一步:打开菜单栏下的tools>command palette或是快捷键ctrl+shift+p输入PI 点击第一个安装包等待跳出窗口,输入ColorPicker,待安装完成 第二步 ...

  10. IntelliJ IDEA 自动导入包 关闭重复代码提示

    idea可以自动优化导入包,但是有多个同名的类调用不同的包,必须自己手动Alt+Enter设置 设置idea导入包 勾选标注 1 选项,IntelliJ IDEA 将在我们书写代码的时候自动帮我们优化 ...