Knex可以在Node.JS和浏览器中用作SQL查询生成器,但限于WebSQL的约束(例如无法删除表或读取模式)。不建议在浏览器中编写SQL查询以在服务器上执行,因为这可能会导致严重的安全漏洞。在WebSQL外部构建的浏览器主要是出于学习目的-例如,您可以弹出控制台并使用knex对象在此页面上构建查询。
Node.js
Knex的主要目标环境是Node.js,您需要安装该knex
库,然后安装适当的数据库库:pg
PostgreSQL和Amazon Redshift,mysql
MySQL或MariaDB,sqlite3
SQLite3或mssql
MSSQL。
$ npm install knex --save
# Then add one of the following (adding a --save) flag:
$ npm install pg
$ npm install sqlite3
$ npm install mysql
$ npm install mysql2
$ npm install oracledb
$ npm install mssql
如果要使用MariaDB实例,则可以使用mysql
驱动程序。
浏览器
Knex可以使用JavaScript构建工具,例如内置browserify或的WebPack。实际上,本文档使用包含knex的webpack构建。在此页面上查看源代码以查看浏览器的实际运行情况(全局knex
变量)。
初始化库
该knex
模块本身就是一个函数,它接受Knex的配置对象,并接受一些参数。该client
参数是必需的,并确定将哪个客户端适配器与库一起使用。
var knex = require('knex')({
client: 'mysql',
connection: {
host : '127.0.0.1',
user : 'your_database_user',
password : 'your_database_password',
database : 'myapp_test'
}
});
连接选项直接传递到适当的数据库客户端以创建连接,并且可以是对象,连接字符串或返回对象的函数:
注意:Knex的PostgreSQL客户端允许您使用附加选项“ searchPath”自动为每个连接设置初始搜索路径,如下所示。
var pg = require('knex')({
client: 'pg',
connection: process.env.PG_CONNECTION_STRING,
searchPath: ['knex', 'public'],
});
注意:使用SQLite3适配器时,需要文件名而不是网络连接。例如:
var knex = require('knex')({
client: 'sqlite3',
connection: {
filename: "./mydb.sqlite"
}
});
注意:当您使用PostgreSQL适配器连接非标准数据库时,可以在knex配置中添加数据库版本。
var knex = require('knex')({
client: 'pg',
version: '7.2',
connection: {
host : '127.0.0.1',
user : 'your_database_user',
password : 'your_database_password',
database : 'myapp_test'
}
});
var knex = require('knex')({
client: 'mysql',
version: '5.7',
connection: {
host : '127.0.0.1',
user : 'your_database_user',
password : 'your_database_password',
database : 'myapp_test'
}
});
可以使用一个函数动态确定连接配置。此函数不接收任何参数,并返回配置对象或对配置对象的承诺。
var knex = require('knex')({
client: 'sqlite3',
connection: () => ({
filename: process.env.SQLITE_FILENAME
})
});
默认情况下,将缓存通过函数接收的配置对象,并将其重新用于所有连接。若要更改此行为,expirationChecker
可以将函数作为配置对象的一部分返回。在expirationChecker
尝试创建新的连接前,征求意见,并在情况下,它会返回true
,新的配置对象被检索。例如,要使用寿命有限的身份验证令牌:
var knex = require('knex')({
client: 'postgres',
connection: async () => {
const { token, tokenExpiration } = await someCallToGetTheToken();
return {
host : 'your_host',
user : 'your_database_user',
password : token,
database : 'myapp_test',
expirationChecker: () => {
return tokenExpiration <= Date.now();
}
};
}
});
您也可以通过unix域套接字连接,该套接字将忽略主机和端口。
var knex = require('knex')({
client: 'mysql',
connection: {
socketPath : '/path/to/socket.sock',
user : 'your_database_user',
password : 'your_database_password',
database : 'myapp_test'
}
});
userParams
是一个可选参数,允许您传递可通过knex.userParams
属性访问的任意参数:
var knex = require('knex')({
client: 'mysql',
connection: {
host : '127.0.0.1',
user : 'your_database_user',
password : 'your_database_password',
database : 'myapp_test'
},
userParams: {
userParam1: '451'
}
});
初始化库通常只应在应用程序中发生一次,因为它会为当前数据库创建一个连接池,因此应在整个库中使用从initialize调用返回的实例。
为您感兴趣的特定SQL类型指定客户端。
var pg = require('knex')({client: 'pg'});
knex('table').insert({a: 'b'}).returning('*').toString();
// "insert into "table" ("a") values ('b')"
pg('table').insert({a: 'b'}).returning('*').toString();
// "insert into "table" ("a") values ('b') returning *"
获取参数化实例
withUserParams
如果要获取具有自定义参数的副本(具有相同的连接),可以在Knex实例上调用method (例如,执行具有不同参数的相同迁移)
var knex = require('knex')({
// Params
});
var knexWithParams = knex.withUserParams({customUserParam: 'table1'});
var customUserParam = knexWithParams.userParams.customUserParam;
调试
debug: true
在初始化对象上传递标志将打开所有查询的调试功能。
asyncStackTraces
asyncStackTraces: true
在初始化对象上传递标志将打开所有查询构建器,原始查询和模式构建器的堆栈跟踪捕获。当数据库驱动程序返回错误时,将捕获此先前捕获的堆栈跟踪,而不是新的堆栈跟踪。这有助于减轻await
node.js / V8中的默认行为,这会破坏堆栈。这具有较小的性能开销,因此建议仅用于开发。默认关闭。
Pooling
由配置创建的客户端使用tarn.js库初始化连接池。该连接池min: 2, max: 10
的MySQL和PG库的默认设置为a ,而sqlite3的连接为单个连接(由于在单个文件上使用多个连接的问题)。要更改池的配置设置,请将一个pool
选项作为初始化块中的键之一传递。
查看tarn.js库以获取更多信息。
var knex = require('knex')({
client: 'mysql',
connection: {
host : '127.0.0.1',
user : 'your_database_user',
password : 'your_database_password',
database : 'myapp_test'
},
pool: { min: 0, max: 7 }
});
如果您需要显式拆除连接池,则可以使用knex.destroy([callback])
。您可以knex.destroy
通过传递回调或将链作为承诺来使用,但不能同时使用。要手动初始化销毁的连接池,可以使用knex.initialize([config]),如果未传递任何配置,它将使用所使用的第一个knex配置。
afterCreate
afterCreate
当池从数据库服务器获取新连接时,将调用回调(rawDriverConnection,已完成)。必须调用done(err,connection)回调,knex
以便能够确定连接是否正常,或者是否应立即从池中将其丢弃。
var knex = require('knex')({
client: 'pg',
connection: {...},
pool: {
afterCreate: function (conn, done) {
// in this example we use pg driver's connection API
conn.query('SET timezone="UTC";', function (err) {
if (err) {
// first query failed, return error and don't try to make next query
done(err, conn);
} else {
// do the second query...
conn.query('SELECT set_limit(0.01);', function (err) {
// if err is not falsy, connection is discarded from pool
// if connection aquire was triggered by a query the error is passed to query promise
done(err, conn);
});
}
});
}
}
});
acquisitionConnectionTimeout
acquireConnectionTimeout
默认值为60000ms,用于确定在无法获取连接时,knex在引发超时错误之前应等待多长时间。造成这种情况的最常见原因是耗尽了所有池的事务连接,然后在池仍然满的情况下尝试在事务外部运行查询。引发的错误将提供有关连接所针对的查询的信息,以简化查找罪魁祸首的工作。
var knex = require('knex')({
client: 'pg',
connection: {...},
pool: {...},
acquireConnectionTimeout: 10000
});
fetchAsString
由Oracledb使用。类型数组。有效类型为“ DATE”,“ NUMBER”和“ CLOB”。当查询具有指定类型之一的任何列时,列数据将作为字符串而不是默认表示形式返回。
var knex = require('knex')({
client: 'oracledb',
connection: {...},
fetchAsString: [ 'number', 'clob' ]
});
Migrations
为了方便起见,可以在初始化库时指定任何迁移配置。阅读“ 迁移”部分以了解更多信息和配置选项的完整列表。
var knex = require('knex')({
client: 'mysql',
connection: {
host : '127.0.0.1',
user : 'your_database_user',
password : 'your_database_password',
database : 'myapp_test'
},
migrations: {
tableName: 'migrations'
}
});
postProcessResponse
在将返回的行传递给用户之前,需要修改返回的行。例如,可以使用此钩子对返回的列进行snake_case-> camelCase转换。该queryContext
如果配置为通过查询生成器实例只能queryContext。
var knex = require('knex')({
client: 'mysql',
// overly simplified snake_case -> camelCase converter
postProcessResponse: (result, queryContext) => {
// TODO: add special case for raw results (depends on dialect)
if (Array.isArray(result)) {
return result.map(row => convertToCamel(row));
} else {
return convertToCamel(result);
}
}
});
wrapIdentifier
Knex支持将标识符名称自动转换为每种方言的引用版本。例如'Table.columnName as foo'
对于PostgreSQL转换为“ Table”。“ columnName”作为“ foo”。
有了wrapIdentifier
一个可以覆盖标识符是如何改变的方式。它可以用于覆盖默认功能,例如帮助执行camelCase
-> snake_case
转换。
转换功能wrapIdentifier(value, dialectImpl, context): string
将标识符的每个部分作为一个单独的value
,来自方言实现和的原始转换功能queryContext
,仅当通过builder.queryContext为查询构建器实例配置,并通过schema.queryContext或表为模式构建器实例配置时,此功能才可用.queryContext。例如,查询生成器,knex('table').withSchema('foo').select('table.field as otherName').where('id', 1)
将调用wrapIdentifier
转换为以下值'table'
,'foo'
,'table'
,'field'
,'otherName'
和'id'
。
var knex = require('knex')({
client: 'mysql',
// overly simplified camelCase -> snake_case converter
wrapIdentifier: (value, origImpl, queryContext) => origImpl(convertToSnakeCase(value))
});
日志
Knex包含一些内部日志功能,用于在适用时打印警告,错误,弃用和调试信息。这些日志功能通常记录到控制台,但可以使用log选项覆盖并提供替代功能。不同的日志功能可用于单独的knex实例。
var knex = require('knex')({
log: {
warn(message) {
},
error(message) {
},
deprecate(message) {
},
debug(message) {
},
}
});
TypeScript支持
虽然knex是用JavaScript编写的,但官方支持的TypeScript绑定可用(在knex npm包中)。
但是,应注意,TypeScript支持目前是尽力而为的。Knex具有非常灵活的API,并非所有使用模式都可以进行类型检查,在大多数情况下,我们会在灵活性方面犯错。特别是,缺少类型错误目前不能保证所生成的查询将是正确的,因此即使您使用的是TypeScript,也建议为它们编写测试。
许多API接受TRecord
和TResult
键入参数,通过它们我们可以分别指定数据库表中行的类型和查询结果的类型。当使用支持TypeScript的编辑器(例如VSCode)时,这有助于自动完成。