Skip to content

Three foreign keys referencing same table #266

New issue

Have a question about this project? No Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “No Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? No Sign in to your account

Closed
devuxer opened this issue Jan 14, 2018 · 8 comments
Closed

Three foreign keys referencing same table #266

devuxer opened this issue Jan 14, 2018 · 8 comments

Comments

@devuxer
Copy link

devuxer commented Jan 14, 2018

My Transit model has three foreign keys referencing the Nation model.

When I sync to a SQLite database, however, only the first foreign key gets created.

Am I doing something wrong?

Model

import { AllowNull, BelongsTo, Column, DataType, ForeignKey, Model, PrimaryKey, Table } from "sequelize-typescript";
import Nation from "./Nation";
import Plan from "./Plan";

@Table({ tableName: "Transits" })
export default class Transit extends Model<Transit> {
    @AllowNull(false)
    @PrimaryKey
    @Column(DataType.TEXT)
    public id: string;

    @AllowNull(false)
    @ForeignKey(() => Plan)
    @Column(DataType.TEXT)
    public planId: string;

    @BelongsTo(() => Plan, { onDelete: "cascade" })
    public plan: Plan;

    @AllowNull(false)
    @ForeignKey(() => Nation)
    @Column(DataType.TEXT)
    public originNationId: string;

    @BelongsTo(() => Nation, { onDelete: "no action" })
    public originNation: Nation;

    @AllowNull(false)
    @ForeignKey(() => Nation)
    @Column(DataType.TEXT)
    public destinationNationId: string;

    @BelongsTo(() => Nation, { onDelete: "no action" })
    public destinationNation: Nation;

    @AllowNull(false)
    @Column(DataType.TEXT)
    public vesselName: string;

    @AllowNull(false)
    @ForeignKey(() => Nation)
    @Column(DataType.TEXT)
    public vesselFlagNationId: string;

    @BelongsTo(() => Nation, { onDelete: "no action" })
    public vesselFlagNation: Nation;

    @AllowNull(false)
    @Column(DataType.TEXT)
    public beginDate: string;

    @AllowNull(false)
    @Column(DataType.TEXT)
    public endDate: string;

    @AllowNull(true)
    @Column(DataType.TEXT)
    public details: string;

    @AllowNull(false)
    @Column(DataType.INTEGER)
    public isFirm: boolean;
}

Expected Result (3 references to "Nations")

CREATE TABLE `Transits` (
	`id`	TEXT NOT NULL,
	`planId`	TEXT NOT NULL,
	`originNationId`	TEXT NOT NULL,
	`destinationNationId`	TEXT NOT NULL,
	`vesselName`	TEXT NOT NULL,
	`vesselFlagNationId`	TEXT NOT NULL,
	`beginDate`	TEXT NOT NULL,
	`endDate`	TEXT NOT NULL,
	`details`	TEXT,
	`isFirm`	INTEGER NOT NULL,
	FOREIGN KEY(`destinationNationId`) REFERENCES `Nations`(`id`) ON DELETE NO ACTION ON UPDATE CASCADE,
	FOREIGN KEY(`vesselFlagNationId`) REFERENCES `Nations`(`id`) ON DELETE NO ACTION ON UPDATE CASCADE,
	PRIMARY KEY(`id`),
	FOREIGN KEY(`planId`) REFERENCES `Plans`(`id`) ON DELETE CASCADE ON UPDATE CASCADE,
	FOREIGN KEY(`originNationId`) REFERENCES `Nations`(`id`) ON DELETE NO ACTION ON UPDATE CASCADE
);

Actual Result (1 reference to "Nations")

CREATE TABLE `Transits` (
	`id`	TEXT NOT NULL,
	`planId`	TEXT NOT NULL,
	`originNationId`	TEXT NOT NULL,
	`destinationNationId`	TEXT NOT NULL,
	`vesselName`	TEXT NOT NULL,
	`vesselFlagNationId`	TEXT NOT NULL,
	`beginDate`	TEXT NOT NULL,
	`endDate`	TEXT NOT NULL,
	`details`	TEXT,
	`isFirm`	INTEGER NOT NULL,
	FOREIGN KEY(`planId`) REFERENCES `Plans`(`id`) ON DELETE CASCADE ON UPDATE CASCADE,
	PRIMARY KEY(`id`),
	FOREIGN KEY(`originNationId`) REFERENCES `Nations`(`id`) ON DELETE NO ACTION ON UPDATE CASCADE
);
@RobinBuschmann
Copy link
Member

Hey @devuxer, sry for the late response. You need to define which foreign key should be used for which relation. So the relations should look like:

@BelongsTo(() => Nation, { onDelete: "no action", foreignKey: "originNationId"})
originNation: Nation;

@BelongsTo(() => Nation, { onDelete: "no action", foreignKey: "destinationNationId" })
destinationNation: Nation;

@BelongsTo(() => Nation, { onDelete: "no action", foreignKey: "vesselFlagNationId" })
vesselFlagNation: Nation;

Probably an error message in case of multiple foreignKey that targets the same Model would be helpful 🤔

@devuxer
Copy link
Author

devuxer commented Jan 16, 2018

Hey @RobinBuschmann,

Thank you for the answer and this very handy library 👍

An error message would definitely help. Perhaps adding this multiple-foreign-key use case to the documentation as well.

One thing that confuses me is why I need @BelongsTo for @ForeignKey to work. I don't actually need the navigation properties (like originNation) in this particular case. I just added them because when I didn't have them, no foreign keys would get added to the database at all.

@RobinBuschmann
Copy link
Member

This is because @ForeignKey is more a helper for the @BelongsTo, @BelongsToMany and so on annotations then an independent decorator. In your case, since you need to define the foreign keys in the @BelongsTo annotation, you can omit the foreign key annotated properties completely.

Ones might consider extending the functionalities of the @ForeignKey decorator...

@devuxer
Copy link
Author

devuxer commented Jan 19, 2018

Ahh OK, makes sense.

So if I want the foreign key to be nullable, I would put@AllowNull on the @BelongsTo property instead of the foreign key property?

@Arloh1
Copy link

Arloh1 commented Feb 12, 2018

This is because @foreignkey is more a helper for the @BelongsTo, @BelongsToMany and so on annotations then an independent decorator. In your case, since you need to define the foreign keys in the @BelongsTo annotation, you can omit the foreign key annotated properties completely.

Ones might consider extending the functionalities of the @foreignkey decorator...

@RobinBuschmann
Copy link
Member

@devuxer I've completely overseen your last question - sry for that. You need to set allowNull in the options of the BelongsTo annotation like so:

@BelongsTo(() => Nation, {
    foreignKey: {
      allowNull: true
    }
  })

@EgoBrainProgrammer
Copy link

Hello @RobinBuschmann Thank you a lot for answers about several FK referencing same table. But can you explain how to implement model association in this case? (getters and setters methods)

@BelongsTo(() => User, { foreignKey: { 
    name: "createUserId", 
    allowNull: true
} })
createUser: User;

@BelongsTo(() => User, { foreignKey: {
    name: "updateUserId",
    allowNull: true
 } })
updateUser: User;

public getCreateUser!: BelongsToGetAssociationMixin<User>;
public getUpdateUser!: BelongsToGetAssociationMixin<User>; //--What field will be used?--

@sa698
Copy link

sa698 commented Nov 16, 2022

how to defin hasmany at National table?

No Sign up for free to join this conversation on GitHub. Already have an account? No Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants