7
votes

I use Typeorm, and simply I want to insert a row by using relationId. But it's not working as I expected.

Here is my entity,

@Entity()
export default class Address extends BaseEntity {

    @Column({
        type: 'varchar',
        length: 255,
    })
    public title: number;

    @Column({
        type: 'varchar',
        length: 2000,
    })
    public value: number;

    @ManyToOne(type => User, user => user)
    @JoinColumn({ name: 'userId' })
    public user: User;

    @RelationId((address: Address) => address.user)
    public userId: number;

}

When I try to add like the below example, it adds null userId which I do not expect

{
    "title": "My home address",
    "value": "Lorep Ipsum Sit Amet",
    "userId": 4
}

enter image description here

When I change the payload, everything works perfectly.

{
    "title": "Ev adresim",
    "value": "Nova Suites",
    "user": 4
}

I do not want to use a payload like the above. I addicted to define a descriptive variable naming. Thanks for all contribution and all answer from now.

3

3 Answers

12
votes

It looks like this is a TypeORM issue with the @RelationId decorator: https://github.com/typeorm/typeorm/issues/3867.

Instead of using @RelationId you can decorate the userId with @Column, when the name of the JoinColumn is equal to the number column name, TypeORM matches both and you can either set the userId or the user and TypeORM will handle it:

@ManyToOne(type => User, user => user)
@JoinColumn({ name: 'userId' })
public user: User;

@Column()
public userId: number;
2
votes

The @RelationId decorator works in one direction. As written in the documentation:

Loads id (or ids) of specific relations into properties.

Relation id is used only for representation. The underlying relation is not added/removed/changed when chaining the value.

As suggested, You can use the @Column decorator to to update the value.

1
votes

As Noam has pointed out, you cannot use the @RelationId() decorated property to assign a relation. Instead you should use the relation itself.

If you have an instance of the object like user below, you can pass it straight away. For the offer I had only ID, I've been able to work around this limitation though by creating an object with just an id property. Now I don't have to retrieve the whole object from the DB which would be waste of resources.

subscriptionRepository
    .insert({
        offer: {id: offerId},
        user: user,
    })

For your reference, this is an excerpt of my entity definition.

@Entity()
export class Subscription {
    @PrimaryGeneratedColumn()
    id: number;

    @ManyToOne(
        () => Offer,
        (offer: Offer) => offer.subscriptions
    )
    offer: Offer;

    @ManyToOne(
        () => User,
        (user: User) => user.subscriptions
    )
    user: User;
}