我正在学习BookshelfJS / KnexJS(从SequelizeJS切换),并且遇到了将数据导入通过KnexJS中的迁移功能创建的多个表中的问题。有4张桌子:
servers
operating_systems
applications
applications_servers
具有以下约束:
servers
。operating_system_id
参考operating_systems
。id
applications_servers
。server_id
参考servers
。id
applications_servers
。application_id
参考applications
。id
在运行时创建表就很好了knex migrate:latest --env development servers
,就是在将种子数据导入表中时出现错误。
最初,我将4个表的种子数据组织为目录中的4个不同文件./seeds/dev
,即${table_name}.js
:
operating_systems.js
servers.js
applications.js
applications_servers.js
有点调试后,我又意识到正在生成的错误时,文件中的种子数据applications_servers.js,因为当我拿一个出来,其他3跑就好了。然后,当我删除3个种子文件并将applications_servers.js移至./seeds/dev/目录并执行时knex seed:run
,applicationsservers表就可以很好地填充了。但是,当我尝试一次导入所有4个文件的种子数据时,收到以下错误:
# knex seed:run Using environment: development Error: ER_NO_REFERENCED_ROW_2: Cannot add or update a child row: a foreign key constraint fails (`bookshelf_knex_lessons`.`applications_servers`, CONSTRAINT `applications_servers_server_id_foreign` FOREIGN KEY (`server_id`) REFERENCES `servers` (`id`) ON DELETE CASCADE) at Query.Sequence._packetToError (/Users/me/Documents/scripts/js/node/bookshelf_knex/node_modules/mysql/lib/protocol/sequences/Sequence.js:48:14) at Query.ErrorPacket (/Users/me/Documents/scripts/js/node/bookshelf_knex/node_modules/mysql/lib/protocol/sequences/Query.js:83:18)
不会在任何表中插入一行。
我认为也许与它们被导入的顺序有关。(因为必须按照上面列出的顺序导入它们)。因此,考虑到它们可能是以字母数字顺序引用的,因此我将其重命名为:
1-operating_systems.js
2-servers.js
3-applications.js
4-applications_servers.js
但是,什么都没有改变,没有任何行插入到任何表中,所以可以肯定的是,我颠倒了文件上数字前缀的顺序,再次,没有任何改变,没有插入任何一行,并且返回了相同的错误。
注意:用于创建表以及所有种子数据的迁移脚本是从我创建的JS文件复制并粘贴的,该JS文件使用BookshelfJS / KnexJS创建了相同的表并导入了相同的数据,但没有使用迁移功能,它只是在通过节点执行时手动执行。您可以在这里查看此文件
任何帮助,将不胜感激!
编辑:当我将./seeds/dev中的所有种子文件合并到一个文件./seeds/dev/servers.js中时,一切都可以导入了。这使我认为这可能是由于knex迁移异步执行所致,因此ID插入了数据透视表中,而则插入了servers
。operating_system_id
可能尚未插入关联的表中...如果是这种情况,是否可以在种子文件中设置依赖项?
Knex.js的种子功能不提供任何顺序的执行保证。应该编写每个种子,以便可以独立执行它。您的单个文件方法是正确的。
如果要将单个种子文件分成子模块,则可以尝试以下操作:
// initial-data.js var operatingSystems = require('./initial-data/operating-systems.js'); var servers = require('./initial-data/servers.js'); exports.seed = function(knex, Promise) { return operatingSystems.seed(knex, Promise) .then(function () { return servers.seed(knex, Promise); }).then(function() { // next ordered migration... }); }