当我在模型中添加Sequelize的关联时,我遇到了错误“ ...用非Sequelize.Model的子类调用的错误”,它称为错误,称为“我不是Sequelize Model”。
E:...\Projects\WebApps\hr1\hr1\node_modules\sequelize\lib\associations\mixin.js:81
throw new Error(this.name + '.' + Utils.lowercaseFirst(Type.toString()) + ' called with something that\'s not a subclass of Sequelize.Model');
^
Error: user_employee_tm.class BelongsTo extends Association {
constructor(source, target, options) {
super(source, target, options);
this.associationType = 'BelongsTo';
this.isSingleAssociation = true;
this.foreignKeyAttribute = {};
if (this.as) {
this.isAliased = true;
this.options.name = {
singular: this.as
};
} else {
this.as = this.target.options.name.singular;
this.options.name = this.target.options.name;
}
if (_.isObject(this.options.foreignKey)) {
this.foreignKeyAttribute = this.options.foreignKey;
this.foreignKey = this.foreignKeyAttribute.name || this.foreignKeyAttribute.fieldName;
} else if (this.options.foreignKey) {
this.foreignKey = this.options.foreignKey;
}
if (!this.foreignKey) {
this.foreignKey = Utils.camelizeIf(
[
Utils.underscoredIf(this.as, this.source.options.underscored),
this.target.primaryKeyAttribute
].join('_'),
!this.source.options.underscored
);
}
this.identifier = this.foreignKey;
if (this.source.rawAttributes[this.identifier]) {
this.identifierField = this.source.rawAttributes[this.identifier].field || this.identifier;
}
this.targetKey = this.options.targetKey || this.target.primaryKeyAttribute;
this.targetKeyField = this.target.rawAttributes[this.targetKey].field || this.targetKey;
this.targetKeyIsPrimary = this.targetKey === this.target.primaryKeyAttribute;
this.targetIdentifier = this.targetKey;
this.associationAccessor = this.as;
this.options.useHooks = options.useHooks;
// Get singular name, trying to uppercase the first letter, unless the model forbids it
const singular = Utils.uppercaseFirst(this.options.name.singular);
this.accessors = {
get: 'get' + singular,
set: 'set' + singular,
create: 'create' + singular
};
}
// the id is in the source table
injectAttributes() {
const newAttributes = {};
newAttributes[this.foreignKey] = _.defaults({}, this.foreignKeyAttribute, {
type: this.options.keyType || this.target.rawAttributes[this.targetKey].type,
allowNull: true
});
if (this.options.constraints !== false) {
const source = this.source.rawAttributes[this.foreignKey] || newAttributes[this.foreignKey];
this.options.onDelete = this.options.onDelete || (source.allowNull ? 'SET NULL' : 'NO ACTION');
this.options.onUpdate = this.options.onUpdate || 'CASCADE';
}
Helpers.addForeignKeyConstraints(newAttributes[this.foreignKey], this.target, this.source, this.options, this.targetKeyField);
Utils.mergeDefaults(this.source.rawAttributes, newAttributes);
this.identifierField = this.source.rawAttributes[this.foreignKey].field || this.foreignKey;
this.source.refreshAttributes();
Helpers.checkNamingCollision(this);
return this;
}
mixin(obj) {
const methods = ['get', 'set', 'create'];
Helpers.mixinMethods(this, obj, methods);
}
/**
* Get the associated instance.
*
* @param {Object} [options]
* @param {String|Boolean} [options.scope] Apply a scope on the related model, or remove its default scope by passing false.
* @param {String} [options.schema] Apply a schema on the related model
* @see {@link Model.findOne} for a full explanation of options
* @return {Promise<Model>}
*/
get(instances, options) {
const association = this;
const where = {};
let Target = association.target;
let instance;
options = Utils.cloneDeep(options);
if (options.hasOwnProperty('scope')) {
if (!options.scope) {
Target = Target.unscoped();
} else {
Target = Target.scope(options.scope);
}
}
if (options.hasOwnProperty('schema')) {
Target = Target.schema(options.schema, options.schemaDelimiter);
}
if (!Array.isArray(instances)) {
instance = instances;
instances = undefined;
}
if (instances) {
where[association.targetKey] = {
[Op.in]: instances.map(instance => instance.get(association.foreignKey))
};
} else {
if (association.targetKeyIsPrimary && !options.where) {
return Target.findByPk(instance.get(association.foreignKey), options);
} else {
where[association.targetKey] = instance.get(association.foreignKey);
options.limit = null;
}
}
options.where = options.where ?
{[Op.and]: [where, options.where]} :
where;
if (instances) {
return Target.findAll(options).then(results => {
const result = {};
for (const instance of instances) {
result[instance.get(association.foreignKey, {raw: true})] = null;
}
for (const instance of results) {
result[instance.get(association.targetKey, {raw: true})] = instance;
}
return result;
});
}
return Target.findOne(options);
}
/**
* Set the associated model.
*
* @param {Model|String|Number} [newAssociation] An persisted instance or the primary key of an instance to associate with this. Pass `null` or `undefined` to remove the association.
* @param {Object} [options] Options passed to `this.save`
* @param {Boolean} [options.save=true] Skip saving this after setting the foreign key if false.
* @return {Promise}
*/
set(sourceInstance, associatedInstance, options) {
const association = this;
options = options || {};
let value = associatedInstance;
if (associatedInstance instanceof association.target) {
value = associatedInstance[association.targetKey];
}
sourceInstance.set(association.foreignKey, value);
if (options.save === false) return;
options = _.extend({
fields: [association.foreignKey],
allowNull: [association.foreignKey],
association: true
}, options);
// passes the changed field to save, so only that field get updated.
return sourceInstance.save(options);
}
/**
* Create a new instance of the associated model and associate it with this.
*
* @param {Object} [values]
* @param {Object} [options] Options passed to `target.create` and setAssociation.
* @see {@link Model#create} for a full explanation of options
* @return {Promise}
*/
create(sourceInstance, values, fieldsOrOptions) {
const association = this;
const options = {};
if ((fieldsOrOptions || {}).transaction instanceof Transaction) {
options.transaction = fieldsOrOptions.transaction;
}
options.logging = (fieldsOrOptions || {}).logging;
return association.target.create(values, fieldsOrOptions).then(newAssociatedObject =>
sourceInstance[association.accessors.set](newAssociatedObject, options)
);
}
} called with something that's not a subclass of Sequelize.Model
at Function.<anonymous> (E:...\Projects\WebApps\hr1\hr1\node_modules\sequelize\lib\associations\mixin.js:81:13)
at Object.<anonymous> (E:...\Projects\WebApps\hr1\hr1\models\user_employee.js:22:14)
at Module._compile (internal/modules/cjs/loader.js:688:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:699:10)
at Module.load (internal/modules/cjs/loader.js:598:32)
at tryModuleLoad (internal/modules/cjs/loader.js:537:12)
at Function.Module._load (internal/modules/cjs/loader.js:529:3)
at Module.require (internal/modules/cjs/loader.js:636:17)
at require (internal/modules/cjs/helpers.js:20:18)
at Object.<anonymous> (E:...\Projects\WebApps\hr1\hr1\models\user.js:4:26)
at Module._compile (internal/modules/cjs/loader.js:688:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:699:10)
at Module.load (internal/modules/cjs/loader.js:598:32)
at tryModuleLoad (internal/modules/cjs/loader.js:537:12)
at Function.Module._load (internal/modules/cjs/loader.js:529:3)
at Module.require (internal/modules/cjs/loader.js:636:17)
at require (internal/modules/cjs/helpers.js:20:18)
at Object.<anonymous> (E:...\Projects\WebApps\hr1\hr1\routes\index.js:4:12)
at Module._compile (internal/modules/cjs/loader.js:688:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:699:10)
at Module.load (internal/modules/cjs/loader.js:598:32)
at tryModuleLoad (internal/modules/cjs/loader.js:537:12)
这是我的验证码
model / User.js
var bcrypt = require('bcrypt');
const sequelize = require('../config/connectionDatabase')
var Sequelize = require('sequelize');
const UserEmployee = require('../models/user_employee');
var User = sequelize.define('user_tm', {
NameFirst: {
type: Sequelize.STRING
},
NameLast: {
type: Sequelize.STRING
},
username: {
type: Sequelize.STRING,
unique: true,
allowNull: false
},
password: {
type: Sequelize.STRING,
allowNull: false
}
}, {
hooks: {
beforeCreate: (user) => {
const salt = bcrypt.genSaltSync();
user.password = bcrypt.hashSync(user.password, salt);
}
},
instanceMethods: {
validPassword: function(password) {
return bcrypt.compareSync(password, this.password);
}
}
});
User.hasOne(UserEmployee, {foreignKey: 'UserID', as: 'User'});
User.prototype.validPassword = function (password) {
return bcrypt.compareSync(password, this.password);
};
module.exports = User;
model / user_employee.js
const sequelize = require('../config/connectionDatabase');
var Sequelize = require('sequelize');
const User = require('../models/user');
var UserEmployee = sequelize.define('user_employee_tm', {
DateJoin: {
type: Sequelize.DATE
},
UserID: {
type: Sequelize.INTEGER,
references: {
model: User,
key: "ID"
}
},
CompanyID: {
type: Sequelize.INTEGER
}
});
// UserEmployee.hasOne(User, {as: 'User', foreignKey: 'UserID'});
UserEmployee.belongsTo(User , {foreignKey: 'ID', as: 'Employee'});
module.exports = UserEmployee;
有什么我想念的吗?我尝试使用此网址 https://dreamdevourer.com/example-of-sequelize-associations-in-feathersjs/
用于与模型一起添加关联,但仍然存在相同的问题。
非常感谢您的帮助
答案 0 :(得分:8)
放入
A.hasOne(B)
和
同一文件中的B.belongsTo(A)
为我解决了这个问题。
答案 1 :(得分:3)
您需要在名为associate(models)
的函数中添加关联。 models
参数包含所有现有的Model
定义,这些定义均以定义名称(在这种情况下为“ user_tm”)作为关键字。
var User = sequelize.define('user_tm', {
// ... user_tm definition
});
var UserEmployee = sequelize.define('user_employee_tm', {
// ... user_employee_tm definition
});
UserEmployee.associate = (models) => {
UserEmployee.belongsTo(models.user_tm, {foreignKey: 'ID', as: 'Employee'});
};
答案 2 :(得分:3)
我是这样解决的:A.hasMany(models.B);在 A 模型上然后在 B 模型上 B.belongsTo(models.A);
"use strict";
const { Model } = require("sequelize");
const quotation = require("./quotation");
module.exports = (sequelize, DataTypes) => {
class Clients extends Model {
/**
* Helper method for defining associations.
* This method is not a part of Sequelize lifecycle.
* The `models/index` file will call this method automatically.
*/
static associate(models) {
// define association here
Clients.hasOne(models.Quotation);
}
}
Clients.init(
{
firstName: DataTypes.STRING,
lastName: DataTypes.STRING,
email: DataTypes.STRING,
phone: DataTypes.STRING,
contactName: DataTypes.STRING,
contactPosition: DataTypes.STRING,
rncCode: DataTypes.STRING,
active: DataTypes.BOOLEAN,
},
{
sequelize,
modelName: "Clients",
}
);
return Clients;
};
"use strict";
const { Model } = require("sequelize");
const quotation = require("./quotation");
module.exports = (sequelize, DataTypes) => {
class Clients extends Model {
/**
* Helper method for defining associations.
* This method is not a part of Sequelize lifecycle.
* The `models/index` file will call this method automatically.
*/
static associate(models) {
// define association here
Clients.hasOne(models.Quotation);
}
}
Clients.init(
{
firstName: DataTypes.STRING,
lastName: DataTypes.STRING,
email: DataTypes.STRING,
phone: DataTypes.STRING,
contactName: DataTypes.STRING,
contactPosition: DataTypes.STRING,
rncCode: DataTypes.STRING,
active: DataTypes.BOOLEAN,
},
{
sequelize,
modelName: "Clients",
}
);
return Clients;
};
答案 3 :(得分:1)
仅对于未来的Google员工来说,这看起来也不错,但是存在循环依赖关系。在我的情况下,A与B有一个belongsTo关系,当我在B上实例化A的钩子时,出现了错误(实际上,它是在您添加import
时出现的)。
我通过在A文件上添加钩子来修复它。
答案 4 :(得分:0)
结果发现我只需要定义UserEmployee的对象 这是我已修复的代码
const sequelize = require('../config/connectionDatabase');
var Sequelize = require('sequelize');
const User = require('../models/user');
const Company = require('../models/company');
var UserEmployee = sequelize.define('user_employee_tm', {
DateJoin: {
type: Sequelize.DATE
},
UserID: {
type: Sequelize.INTEGER,
references: {
model: User,
key: "UserID"
}
},
CompanyID: {
type: Sequelize.INTEGER,
references: {
model: Company,
key: "CompanyID"
}
}
});
UserEmployee.belongsTo(Company, {as: 'Company', foreignKey: 'CompanyID'});
UserEmployee.belongsTo(User, {as: 'User', foreignKey: 'UserID'});
module.exports = UserEmployee;
由于Sequelize已设置了将它们关联的方法,因此无需将其设置为关联,并且我也已修复了它们之间的关系。
希望其他与我有相同问题的人也可以照看它,而不会使2个模型最终存储在1个文件中。
P.S。 感谢doublesharp为您指出我的错误做法提供的帮助
答案 5 :(得分:0)
我发现了我忘记从型号名称中删除s的问题
User.belongsToMany(models.Roles,{ 通过:“ user_roles”, });
答案 6 :(得分:0)
如果您有很多模型,将所有模型放在一个文件中是不可行的。
对我有用的不是将模型添加到同一个文件中,而是创建一个新的 associations
文件并导入模型,然后在其中执行 belongsTo
等。然后在主应用程序文件中 import './assocations'
。这解决了错误。
associations
文件类似于以下内容:
import {Post} from "./post";
import {Tag} from "./tag";
Tag.belongsToMany(Post, {
through: 'PostTags'
})
Post.belongsToMany(Tag, {
through: 'PostTags'
})
答案 7 :(得分:0)
我是 Sequelize 的新手。这种方法可能很幼稚,但它解决了我的简单用例中的鸡/蛋问题:
模型/Dog.js
const {Model} = require('sequelize');
module.exports = function (sequelize) {
class Dog extends Model {}
setTimeout(() => {
Dog.hasMany(sequelize.models.Flea);
}, 0);
return Dog;
}
models/Flea.js
const {Model} = require('sequelize');
module.exports = function (sequelize) {
class Flea extends Model {}
setTimeout(() => {
Flea.belongsTo(sequelize.models.Dog);
}, 0);
return Flea;
}
models/index.js:
const sequelize = getConnectionSomehow();
const Dog = require('./Dog' )(sequelize);
const Flea = require('./Flea')(sequelize);