#javascript #database #postgresql #sequelize.js
Вопрос:
У меня возникла проблема с обновлением отображаемого имени в таблице пользователей со следующей ошибкой.
ОТНОШЕНИЯ
Пользователь также может быть супервайзером. И обе таблицы имеют поле имени (отображаемое имя пользователя и имя руководителя). Если пользователь X отредактирует свой профиль и изменит имя дисплея, я хочу, чтобы это изменение отразилось в поле имя таблицы супервизора. Я думал, что каскад будет работать, но я его не получал.
(node:25136) UnhandledPromiseRejectionWarning: SequelizeForeignKeyConstraintError: update or delete on table "c_user" violates foreign key constraint "c_supervisor_name_fkey" on table "c_supervisor"
Существует соотношение 1:n между таблицей пользователей и таблицей супервизора.
МОДЕЛЬ ПОЛЬЗОВАТЕЛЯ
const User = sequelize.define('user', {
id: {
type: Sequelize.INTEGER,
allowNull: false,
primaryKey: true,
autoIncrement: true
},
displayName: {
type: Sequelize.STRING,
allowNull: false,
unique: true
},
User.associate = function(models) {
User.hasOne(models.supervisor, { foreignKey: "userId" });
};
User.hasOne(models.supervisor, { foreignKey: "name" });
return User;
};
МОДЕЛЬ СУПЕРВАЙЗЕРА
module.exports = (sequelize, Sequelize) => {
const Supervisor = sequelize.define('supervisor', {
id: {
type: Sequelize.INTEGER,
allowNull: false,
primaryKey: true,
autoIncrement: true
},
userId: {
type: Sequelize.INTEGER,
primaryKey: true,
allowNull: false,
unique: true,
references: {
model: 'c_user',
key: 'id'
}
},
name: {
type: Sequelize.STRING,
allowNull: false,
references: {
model: 'c_user',
key: 'displayName'
}
},
Supervisor.associate = function(models) {
Supervisor.belongsTo(models.user, {
foreignKey: "userId", targetKey: "id", onDelete: "CASCADE", onUpdate: "CASCADE"
});
Supervisor.belongsTo(models.user, {
foreignKey: "name", targetKey: "displayName", onDelete: "CASCADE", onUpdate: "CASCADE"
});
}
return Supervisor;
};
Если я обновлю отображаемое имя в таблице пользователей, я хочу, чтобы оно каскадировалось в имя в супервизоре и обновило его, но вместо этого я получил ошибку выше.
Комментарии:
1. Почему название вообще имеет отношение к отношению?
2. @Andreas у пользователя есть страница профиля, где он может редактировать свое отображаемое имя. Затем у того же пользователя есть поле имени в модели супервизора. Поэтому мы хотим, чтобы, если пользователь изменит имя в модели пользователя, это изменение должно немедленно отразиться в модели супервизора.
3. Это не ответ на мой вопрос. Почему имя хранится в двух местах? И почему он используется в отношениях? Связь строится с идентификатором. Это оно.
4. @Andreas В контроллере супервайзера я использовал идентификатор пользователя для получения отображаемого имени пользователя и использовал его в качестве имени. Во внешнем интерфейсе при заполнении формы супервайзера пользователю нужно только указать идентификатор пользователя. Там нет ввода для имени, которое обрабатывается в бэкэнде. Даже когда я удаляю связь с именем и просто использую идентификатор пользователя для получения имени дисплея, я все равно получаю описанную выше ошибку при попытке обновить имя пользователя.
Ответ №1:
Во-первых, использовать имя в качестве иностранного ключа-плохая идея. И во-вторых, если вы связываете две одинаковые таблицы друг с другом, вам нужно использовать псевдонимы, чтобы различать, как они связаны. Например:
// user-to-supervisor one to one relation as user
User.hasOne(Supervisor, {foreignKey: 'userId', as: 'user'})
Supervisor.belongsTo(User)
// user-to-supervisor one to one relation as username
User.hasOne(Supervisor, {foreignKey: 'name', as: 'username'})
Supervisor.belongsTo(User)
Надеюсь, это поможет, но то, что вы пытаетесь сделать, непрактично.
Можете ли вы рассказать более конкретно об отношениях, которых вы пытаетесь достичь?
Комментарии:
1. Пользователь также может быть супервайзером. И обе таблицы имеют поле имени (отображаемое имя пользователя и имя руководителя). Если пользователь X отредактирует свой профиль и изменит имя дисплея, я хочу, чтобы это изменение отразилось в поле имя таблицы супервизора. Я думал, что каскад будет работать, но я его не получал.
2. @Wacademy вы можете создать только одну модель пользователя и добавить новое поле под названием роль, в котором может быть пользователь, супервайзер.
3. В моей пользовательской модели уже есть роли, но супервизор-это отдельная модель, а не роль. Спасибо