摘要
本人最近完成了一个封装数据库访问抽象层的项目。我们开发的数据库访问抽象层作为分布式集群基础平台的一个组件。可以支持不同数据库编程接口(OCI、mysql、ODBC、pgsql)等。本系列博客主要分享一下我在开发数据库访问抽象层组件的遇到的问题和收获。
在本文主要介绍数据库访问抽象层的概念,常见的几种数据库编程接口ODBC、JDBC、OLE-DB、ADO、OCI等。

数据库访问抽象层的意义
数据库访问抽象层是封装了数据库底层操作的介于应用逻辑程序和数据之间的中间件。目的是为了隐藏因为数据库方言的不同,而在存取数据中的差异。使整个系统在变更商业数据库的时候,做到改动最小,或者只需要修改数据库的配置文件即可。
提供一种轻型、清晰、方便的 API ,统一各种不同 RDBMS 库的共有特性,但不排除更高级的特性。通过动态库提供可选的较大程度的抽象/兼容性。针对以上理解,本文共分为四个部分:
 第一部分是1、2章,主要探讨几种数据库编程接口的选择;
 第二部分是第3章,详细描述ODBC的安装与配置;
 第三部分是4、5章,讨论ODBC的数据类型以及支持的函数;
 第四部分是6章,编写一个ODBC编程接口的测试程序
 第五部分是第7章,作为附录介绍ODBC编程常遇到的两个问题。


1. 概念
服务器后台数据库的编程接口包括OCI、JDBC、ODBC、OLE-DB、ADO,本小节分别阐述几种概念并分析他们之间的关系。
1.1. 什么是JDBC?
Java语言访问数据库的一种规范,是一套API。
JDBC(Java Database connectivity)API,即Java数据库编程接口,是一组标准的Java语言中的接口和类,使用这些接口和类,Java客户端程序可以访问各种不同类型的数据库。比如建立数据库连接、执行SQL语句进行数据的存取操作。
JDBC规范采用接口和实现分离的思想设计了Java数据库的编程框架。接口包含在Java.sql及Javax.sql包中,其中Java.sql属于JavaSE,Javax.sql属于JavaEE。这些接口的实现类叫做数据库驱动程序,由数据库的厂商或其它的厂商或个人提供。


图1-1

1.2. 什么是ODBC?
ODBC(Open Database Connectivity,开放数据库互连)是微软公司开放服务结构(WOSA,Windows Open Services Architecture)中有关数据库的一个组成部分,它建立了一组规范,并提供了一组对数据库访问的标准API(应用程序编程接口)。这些API利用SQL来完成其大部分任务。ODBC本身也提供了对SQL语言的支持,用户可以直接将SQL语句送给ODBC。
应用程序要访问一个数据库,首先必须用ODBC管理器注册一个数据源,管理器根据数据源提供的数据库位置、数据库类型及ODBC驱动程序等信息,建立起ODBC与具体数据库的联系。这样,只要应用程序将数据源名提供给ODBC,ODBC就能建立起与相应数据库的连接。
达梦数据库(DM DATABASE,以下简称DM)的DM ODBC 3.0遵照Microsoft ODBC 3.0规范设计与开发,实现了ODBC应用程序与DM的互连接口。用户可以直接调用DM ODBC 3.0接口函数访问DM,也可以使用可视化编程工具如Visual C++、C++ Builder、PowerBuilder等利用DM ODBC 3.0访问DM。


图 1-2

1.3. 什么是OLE-DB
OLE DB(Object Link and embed 即对象连接与嵌入。)是微软的战略性的通向不同的数据源的低级应用程序接口。OLE DB不仅包括微软资助的标准数据接口开放数据库连通性(ODBC)的结构化问题语言(SQL)能力,还具有面向其他非SQL数据类型的通路。 作为微软的组件对象模型(COM)的一种设计,OLE DB是一组读写数据的方法(在过去可能被称为渠道)。OLD DB中的对象主要包括数据源对象、阶段对象、命令对象和行组对象。使用OLE DB的应用程序会用到如下的请求序列:初始化OLE 连接到数据源 发出命令 处理结果 释放数据源对象并停止初始化OLE
OLE DB标准中定义的新概念—-OLE DB将传统的数据库系统划分为多个逻辑组件,这些组件之间相对独立又相互通信。这种组件模型中的各个部分被冠以不同的名称:数据提供者(Data Provider)。 提供数据存储的软件组件,小到普通的文本文件、大到主机上的复杂数据库,或者电子邮件存储,都是数据提供者的例子。有的文档把这些软件组件的开发商也称为数据提供者。

1.4. 什么是ADO
微软公司的ADO (ActiveX Data Objects)是一个用于存取数据源的COM组件。它提供了编程语言和统一数据访问方式OLE DB的一个中间层。允许开发人员编写访问数据的代码而不用关心数据库是如何实现的,而只用关心到数据库的连接。访问数据库的时候,关于SQL的知识不是必要的,但是特定数据库支持的SQL命令仍可以通过ADO中的命令对象来执行。
ADO被设计来继承微软早期的数据访问对象层,包括RDO (Remote DataObjects)和DAO(Data Access Objects)。ADO在1996年冬被发布。
ADO包括了6个类:Connection,Command,Recordset,Errors,Parameters,Fields。

1.5. OLE-DB 和ODBC的区别
由于OLEDB和ODBC 标准都是为了提供统一的访问数据接口,所以曾经有人疑惑:OLE DB 是不是替代ODBC 的新标准?答案是否定的。实际上,ODBC 标准的对象是基于SQL 的数据源(SQL-Based Data Source),而OLE DB 的对象则是范围更为广泛的任何数据存储。从这个意义上说,符合ODBC 标准的数据源是符合OLE DB 标准的数据存储的子集。

1.6. ADO、OLE-DB和ODBC的关系
通俗点 OLE DB和ODBC都是最底层的东西,而ADO对象给我们提供了一个“可视化”,和应用层直接交互的组件,我们不用过多的关注OLE-DB的内部机制,只需要了解ADO通过OLE-DB创建数据源的几种方法即可,就可以通过ADO轻松地获取数据源。ADO是应用程序和数据底层的一个中间层,ADO对象通过OLE-DB间接取得数据库中的数据。OLE-DB只是提供了通向各种数据库的一个通用接口,可以用下图2-1来表示:


图1-3
1.7 OCI编程接口的简介

请参照如下连接的简介:
http://baike.baidu.com/link?url=i57cAhZrzMiGI1lNLp3se9Tkg_9BSdwDp3K_vVS-IwR5m90mcdsjv_366kASh46xjPRM8kYJs3K0djJG9BSOZ_
pgsql编程接口的简介:
http://baike.baidu.com/link?url=k0sIoIwe9U1ySbQLk6CR3soEFw9smmeF35Q3D7Cz-Etc4GjBgFIc-Ze288J07ECe6xNY6d-dgcgJ3O4A02O1mK


2. 标准接口的选择
2.1. 为什么不选择JDBC?
由1.1和1.2两个小节可知,JDBC属于Java数据库编程接口,ODBC支持C/C++等变成语言。根据需求我们需要封装一套通用C/C++数据库封装层API,故JDBC不可行。

2.2. 为什么不选择ADO?
由2小节可知,ADO是对OLE-DB的封装,优势主要在于易用性和可视化,本质上ADO是数据库访问抽象层。而我们的需求是提供类似PCS系统DBAPI的API接口函数,可以方便的支持不同的数据库。如果选择ADO,则我们需要在ADO的基础上再封装一层API接口,而数据库操作是偏向底层。过多的封装在一定程度上降低整个系统的性能。基于以上原因而不选择ADO。

2.3. 用OLE-DB还是ODBC?
从网络查找资料了解到选择OLE-DB和ODBC的一些基本的原则:
① 非OLE 环境 —— 如果要访问支持ODBC 的数据库,而该数据库又在不支持OLE 的服务器上,那么ODBC 是最好的选择。
② 非SQL 环境 —— ODBC 在处理SQL 时非常出众。处理非SQL 数据库时,OLE-DB则具有非常明显的优势。
③ OLE 环境 —— 对支持OLE 的服务器来说,选择OLE-DB 还是ODBC 也许是希望各半。如果有ODBC 驱动程序可供利用,那么使用ODBC 是一个好主意;否则,就只有选择OLE-DB了。
④ 所需的互操作性 如果需要可互操作的数据库部件,那么只有选择OLE-DB。
综合以上基本原则②和我们的需求,个人认为我们更适合选择ODBC编程接口。
结论
根据以上原则,选择ODBC作为待封装的编程接口。


3. ODBC的安装与配置
使用ODBC 方法访问一个DM 数据库服务器之前,必须先对自己的应用程序所用的ODBC 资源进行配置。本小节将介绍如何在linux环境下安装和配置ODBC 资源。
在 Linux 上配置ODBC 数据源的方式有两种,手动配置和图形配置。下面将以麒麟操作系统为例详细描述Linux环境安装unixODBC数据源、手动配置达梦ODBC数据源。

3.1. 编译和安装unixODBC数据源
① 将压缩包unixODBC-2.3.0.tar.gz上传到 linux /usr/local 下,然后执行 tar -xzvf unixODBC-2.3.0.tar.gz
② 进入cd /usr/local/unixODBC-2.3.0 执行 ./configure –prefix=/usr/local/unixODBC-2.3.0 –includedir=/usr/include –libdir=/lib64/lib -bindir=/usr/bin –sysconfdir=/etc
③ 执行 make
④ 执行 make install
⑤ 通过 odbc_config –version 确定odbc安装是否成功,显示2.3.0表示已经成功安装。

3.2. 配置达梦ODBC资源
达梦数据库ODBC达梦数据库驱动程序如下表格3-1所示。达梦ODBC有两个配置文件odbcinst.ini和odbc.ini。odbcinst.ini文件负责配置DM 数据库ODBC 驱动,odbc.ini文件负责配置 DSN(data source name)。这两个文件的路径通过命令获取,如下图所示。达梦ODBC需要的动态库:libdmapi.so、libdmcrypto_engine.so、libdmodbc.so、libdmucvt.so、libdmzip.so。

[root@localhost etc]# odbc_config --odbcini
/etc/odbc.ini
[root@localhost etc]# odbc_config --odbcinstini
/etc/odbcinst.ini

图3-1

odbcinst.ini文件配置项:
① [dm]设置DSN(data source name)-即设置数据源名。
② Driver指定动态驱动库路经。
odbc.ini文件配置项:
① Driver指定动态驱动库路经;
② SERVER指定数据库节点IP地址
③ UID指定登陆用户名
④ PWD指定登陆密码
⑤ TCP_PORT指定端口号,默认12345
现在通过实例配置文件odbc.ini需要修改字段SERVER,使之等于达梦数据库服务端节点IP。odbcinst.ini需要修改字段Driver,使之与动态库libdmodbc.so实际路径相同(注:与达梦手册中配置不同部分,以本文档为准)。图3-3和图3-4是备调测试系统BDTEST sgs1-net1节点上两个文件配置的两个实例:

[dm]
Description = dm
Driver =dm
SERVER =192.168.200.100
UID=SYSDBA
PWD=SYSDBA
TCP_PORT=12345

图3-3 odbc.ini文件

[dm]
Description=dm
Driver = /etc/dm_odbc_lib/libdmodbc.so

表格 3 4文件odbcinst.ini

配置完成后在任意路径,通过命令测试连接。方法如下图所示:

[root@localhost /]# isql dm SYSDBA SYSDBA
+---------------------------------------+
| Connected!              |
|                        |
| sql-statement            |
| help [tablename]          |
| quit                    |
|                        |
+---------------------------------------+

图 3-5 测试连接


4. ODBC的数据类型
客户程序可以通过SQLGetTypeInfo 函数来获取DM ODBC 3.0 支持的数据类型信息。由
SQLGetTypeInfo 返回的数据类型是数据源所支持的数据类型,它们是预备用于DDL
(DataDefinitionLanguage)语句的。调用 DM ODBC 3.0 的SQLGetTypeInfo,返回支持的数据类型如图5-1如下:


图4-1
注:要支持interval 数据类型,必须在数据源中进行设置,否则将不提供对该类数据类型的支持。变长字符串的最大长度实际上是受库块大小的约束,上面的约束是在库大小为8K 时的最大长度。


5. 达梦ODBC支持的函数
DM ODBC 3.0 遵照Microsoft ODBC 3.0 规范设计与开发

客户程序可以通过SQLGetFunctions 函数来获取DM ODBC 3.0 支持的函数信息。由SQLGetFunctions 返回的函数列表是数据源所支持的函数。以下按照类型分类列出了DM ODBC 3.x 提供的函数。应用程序能够通过调用SQLGetFunctions 来获得指定函数的支持信息。
5.1. 连接到数据源
下面的函数用于连接到数据源:
(1)SQLAllocHandle:分配环境、连接、语句或者描述符句柄。
(2)SQLConnect:建立与驱动程序或者数据源的连接。访问数据源的连接句柄包含了包
括状态、事务申明和错误信息的所有连接信息。
(3)SQLDriverConnect:与SQLConnect 相似,用来连接到驱动程序或者数据源。但它比
SQLConnect 支持数据源更多的连接信息,它提供了一个对话框来提示用户设置所有的连接信息
以及系统信息表没有定义的数据源。
(4)SQLBrowseConnect:支持一种交互方法来检索或者列出连接数据源所需要的属性和
属性值。每次调用函数可以获取一个连接属性字符串,当检索完所有的属性值,就建立起与数
据源的连接,并且返回完整的连接字符串,否则提示缺少的连接属性信息,用户根据此信息重
新输入连接属性值再次调用此函数进行连接。
5.2. 获取驱动程序和数据源信息
下面的函数用来获取驱动程序和数据源信息:
(1)SQLDataSources:能够被调用多次来获取应用程序使用的所有数据源的名字。
(2)SQLDrivers:返回所有安装过的驱动程序清单,包括对它们的描述以及属性关键字。
(3)SQLGetInfo:返回连接的驱动程序和数据源的元信息。
(4)SQLGetFunctions:返回指定的驱动程序是否支持某个特定函数的信息。
(5)SQLGetTypeInfo:返回指定的数据源支持的数据类型的信息。
5.3. 设置或者获取驱动程序属性
下面的函数用来设置或者获取驱动程序属性:
(1)SQLSetConnectAttr:设置连接属性值。
(2)SQLGetConnectAttr:返回连接属性值。
(3)SQLSetEnvAttr:设置环境属性值。
(4)SQLGetEnvAttr:返回环境属性值。
(5)SQLSetStmtAttr:设置语句属性值。
(6)SQLGetStmtAttr:返回语句属性值。
5.4. 设置或者获取描述符字段
下面的函数用来设置或者获取描述符字段:
(1)SQLGetDescField:返回单个描述符字段的值。
(2)SQLGetDescRec:返回当前描述符记录的多个字段的值。
(3)SQLSetDescField:设置单个描述符字段的值。
(4)SQLSetDescRec:设置描述符记录的多个字段。
5.5. 准备SQL 语句
下面的函数用来准备SQL 语句:
(1)SQLPrepare:准备要执行的SQL 语句。
(2)SQLBindParameter:在SQL 语句中分配参数的缓冲区。
(3)SQLGetCursorName:返回与语句句柄相关的游标名称。
(4)SQLSetCursorName:设置与语句句柄相关的游标名称。
(5)SQLSetScrollOptions:设置控制游标行为的选项。
5.6. 提交SQL 请求
下面的函数用来提交SQL 请求:
(1)SQLExecute:执行准备好的SQL 语句。
(2)SQLExecDirect:执行一条SQL 语句。
(3)SQLNativeSql:返回驱动程序对一条SQL 语句的翻译。
(4)SQLDescribeParam:返回对SQL 语句中指定参数的描述。
(5)SQLNumParams:返回SQL 语句中参数的个数。
(6)SQLParamData:与SQLPutData 联合使用在运行时给参数赋值。
(7)SQLPutData:在SQL 语句运行时给部分或者全部参数赋值。
5.7. 检索结果集及其相关信息
下面的函数用来检索结果集及其相关信息:
(1)SQLRowCount:返回INSERT、UPDATE 或者DELETE 等语句影响的行数。
(2)SQLNumResultCols:返回结果集中列的数目。
(3)SQLDescribeCol:返回结果集中列的描述符记录。
(4)SQLColAttribute:返回结果集中列的属性。
(5)SQLBindCol:为结果集中的列分配缓冲区。
(6)SQLFetch:在结果集中检索下一行元组。
(7)SQLFetchScroll:返回指定的结果行。
(8)SQLGetData:返回结果集中当前行某一列的值。
(9)SQLSetPos:在取到的数据集中设置游标的位置。这个记录集中的数据能够刷新、更
新或者删除。
(10)SQLBulkOperations:执行块插入和块书签操作,其中包括根据书签更新、删除或者
取数据。
(11)SQLMoreResults:确定是否能够获得更多的结果集,如果能就执行下一个结果集的
初始化操作。
(12)SQLGetDiagField:返回一个字段值或者一个诊断数据记录。
(13)SQLGetDiagRec:返回多个字段值或者一个诊断数据记录。
5.8. 取得数据源系统表的信息
下面的函数用来取得数据源系统表的信息:
(1)SQLColumnPrivileges:返回一个关于指定表的列的列表以及相关的权限信息。
(2)SQLColumns:返回指定表的列信息的列表。
(3)SQLForeignKeys:返回指定表的外键信息的列表。
(4)SQLPrimaryKeys:返回指定表的主键信息的列表。
(5)SQLProcedureColumns:返回指定存储过程的参数信息的列表。
(6)SQLProcedures:返回指定数据源的存储过程信息的列表。
(7)SQLSpecialColumns:返回唯一确定某一行的列的信息,或者当某一事务修改一行的
时候自动更新各列的信息。
(8)SQLStatistics:返回一个单表的相关统计信息和索引信息。
(9)SQLTablePrivileges:返回相关各表的名称以及相关的权限信息。
(10)SQLTables:返回指定数据源中表信息。
5.9. 终止语句执行
下面的函数用来终止语句执行:
(1)SQLFreeStmt:终止语句执行,关闭所有相关的游标,放弃没有提交的结果,选择释
放与指定语句句柄相关的资源。
(2)SQLCloseCursor:关闭一个打开的游标,放弃没有提交的结果。
(3)SQLCancel:放弃执行一条SQL 语句。
(4)SQLEndTran:提交或者回滚事务。
5.10. 中断连接
下面的函数处理中断连接的任务:
(1)SQLDisconnect:关闭指定连接。
(2)SQLFreeHandle:释放环境、连接、语句或者描述符句柄。
5.11. ODBC编程:
使用ODBC编程的基本步骤如下图所示

图5-2

6编写两个简单建立连接和断开连接的示例程序

6.1建立连接:

int DMODBCDBApi::Connect(const char *pszConnectStr,const char *pszUser,const char *pszPasswd)
{
// 检测返回代码是否为成功标志,当为成功标志时返回TRUE,否则返回FALSE
#define RC_SUCCESSFUL(rc) ((rc) == SQL_SUCCESS || (rc) == SQL_SUCCESS_WITH_INFO)
// 检测返回代码是否为失败标志,当为失败标志时返回TRUE,否则返回FALSE
#define RC_NOTSUCCESSFUL(rc) (!(RC_SUCCESSFUL(rc)))// 申请一个环境句柄SQLAllocHandle(SQL_HANDLE_ENV, NULL, &henv);// 设置环境句柄的ODBC版本SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3,SQL_IS_INTEGER);// 申请一个连接句柄SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);sret = SQLConnect(hdbc, (SQLCHAR *)pszConnectStr, SQL_NTS, (SQLCHAR *)pszUser, SQL_NTS, (SQLCHAR*)pszPasswd, SQL_NTS);if (RC_NOTSUCCESSFUL(sret)){// 连接数据源失败! 进行相应的错误处理printf("RC_NOTSUCCESSFUL!!!\n");SQLFreeHandle(SQL_HANDLE_DBC, hdbc);SQLFreeHandle(SQL_HANDLE_ENV, henv);return -1;}connected = true;printf("CONNECT SUCCESSFUL!!!\n");return 0;
}

6.2 断开连接的示例程序

int DMODBCDBApi::DisConnect()
{// 断开与数据源之间的连接SQLDisconnect(hdbc);// 释放连接句柄SQLFreeHandle(SQL_HANDLE_DBC, hdbc);// 释放环境句柄SQLFreeHandle(SQL_HANDLE_ENV, henv);// 连接状态为断开connected = false;hdbc = NULL;henv = NULL;return 0;
}

6.3 Makefile编写的关键点注意

INCDIR = -I. -I/usr/include/
LIBDIR = -L/lib64/lib
LIBS = -lodbc
#连接的是UnixODBC数据源动态库,而不是达梦ODBC动态库

7. 附录
在探索过程中发现,觉得在以后编程实战也可能遇到的问题记录如下:
7.1. 调用达梦动态库段错误
解决方法:
编写makefile的时候,连接的动态库是UnixODBC数据源的动态库而非达梦的动态库;
7.2. 打不开动态库
如下图所示:cannot open shared object file: No such file or directory

sgs1-net2:/lib64/lib # ls libodbc.so.1
libodbc.so.1
但是ldd命令找不到,说明程序运行加载动态库的时候未搜索到libodbc.so.1。
于是找到解决方案:
vi /etc/ld.so.conf
加入路径/lib64/lib,如下所示:

图 7-2
执行命令/sbin/ldconfig –v 更新程序加载动态库的路径

数据库访问抽象层系列-1(介绍数据库编程接口及数据库访问抽象层概念)相关推荐

  1. java 接口访问权限_详解Java之路(五) 访问权限控制

    在Java中,所有事物都具有某种形式的访问权限控制. 访问权限的控制等级从最大到最小依次为:public,protected,包访问权限(无关键词)和private. public,protected ...

  2. h2 不能访问localhost_SpringBoot2.x系列教程44--H2数据库详解及搭建Web控制台

    SpringBoot2.x系列教程44--H2数据库详解及搭建Web控制台 作者:一一哥 我在上一章节中讲解了Spring Boot中整合Mybatis,接下来我给大家介绍一款内存数据库--H2. H ...

  3. ElasticSearch学习系列(一)关于ES数据库的和核心倒排索引的介绍

    关于ES数据库的和核心倒排索引的介绍 一.Elasticsearch概述 简介 关于全文检索引擎 关系型数据库的全文检索功能缺点 全文检索的应用场景 Elasticsearch 应用案例 二.Elas ...

  4. 【愚公系列】2022年01月 Mysql数据库-Mysql介绍和安装

    文章目录 前言 一.数据库的基本概念 1.为什么要学数据库? 2.什么是数据库? 3.数据库的好处? 4.常见的数据库有哪些? 二.MySQL数据库的安装 1.MySQL数据库介绍 2.MySQL数据 ...

  5. phoenix 开发API系列(三)phoenix api 结合数据库

    概述 介绍了 api 的各种写法之后,下面介绍构建 api 时与数据库连接的方式. 注 下面使用的工程的完整代码已经公开在: http://git.oschina.net/wangyubin/phoe ...

  6. Spring Boot干货系列:数据存储篇-SQL关系型数据库之MyBatis的使用

    Spring Boot干货系列:数据存储篇-SQL关系型数据库之MyBatis的使用 前言 上篇我们介绍了Spring Boot对传统JdbcTemplate的集成,这次换一下,介绍下Spring B ...

  7. 核心项目:高并发秒杀系统(项目介绍,项目搭建,数据库,DAO)

    1,项目介绍 1.1,问题难点 在原SSH基础上,替换为SpringBoot系统,模拟了高并发场景的商城系统,它具备秒杀功能,并在经过几个版本的迭代之后成为支持高并发的高性能系统.这种秒杀活动会让用户 ...

  8. boot spring test 文档_SpringBoot入门建站全系列(五)使用Spring-data-jpa操作数据库

    SpringBoot入门建站全系列(五)使用Spring-data-jpa操作数据库 SpringBoot操作数据库有多种方式,如 JDBC直接操作:太古老了,没人愿意这样玩 Mybatis插件:比较 ...

  9. Redis 学习笔记-NoSQL数据库 常用五大数据类型 Redis配置文件介绍 Redis的发布和订阅 Redis_事务_锁机制_秒杀 Redis应用问题解决 分布式锁

    1.NoSQL数据库 1.1 NoSQL数据库概述 NoSQL(NosQL = Not Only sQL ),意即"不仅仅是sQL",泛指非关系型的数据库.NoSQL不依赖业务逻辑 ...

最新文章

  1. 2017 Vue.js 2快速入门指南
  2. 在Golang开发中使用Redis
  3. weka 学习总结(持续)
  4. 归档-软考部分科目的考察内容
  5. 数据库比特币勒索病毒攻击警示,云和恩墨技术通讯六月刊精选
  6. 如何理解nextTick函数
  7. Ubuntu用户连续N次输入错误密码进行登陆时自动锁定X分钟
  8. RPC failed; curl 56 GnuTLS recv error (-54): Error in the pull function.
  9. 怎样规划你毕业以后的人生
  10. “罪魁祸首”已找到,微软回应修改 MIT 开源项目作者版权声明
  11. 【FXCG】美国加息缩表在即,人民币仍创新高
  12. ES6新特性有哪些?
  13. 从头认识一遍“货到人”拣选
  14. Unity3D 游戏贴图(法线贴图,漫反射贴图,高光贴图)
  15. MATLAB矩阵基础知识(二)
  16. Graph Representation Learning 笔记 Ch1Ch2
  17. SIP协议详解(中文)-3
  18. Piggy-Bank(背包)
  19. 10.摆平Linux正则表达式
  20. 城固一中2021年高考成绩查询,城固一中成绩查询系统

热门文章

  1. 每日linux——网络命令2
  2. GMQ Wallet 跨时代产品,全面体现区块链数字资产价值
  3. 这个小学生,竟然把学校的网站搞了!
  4. Powerlevel10k 主题安装
  5. 让Google倒过来:超级搞笑的Google彩蛋
  6. css 实现倒计时转圈动画
  7. AMD要闹哪样!亮出无字天书路线图
  8. 简易UC首页demo续
  9. win10家庭版访问域文件服务器拒绝,win10系统访问文件提示拒绝你访问该文件夹的原因和解决方法...
  10. 网页播放器与播放器定制