Skip to content
New issue

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

By clicking “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? Sign in to your account

Retrieving ID in @AfterInsert operation #3563

Closed
alex5207 opened this issue Feb 2, 2019 · 8 comments
Closed

Retrieving ID in @AfterInsert operation #3563

alex5207 opened this issue Feb 2, 2019 · 8 comments

Comments

@alex5207
Copy link

alex5207 commented Feb 2, 2019

Issue type:

[X ] question
[ ] bug report
[ ] feature request
[ ] documentation issue

Database system/driver:

[ ] cordova
[ ] mongodb
[ ] mssql
[X ] mysql / mariadb
[ ] oracle
[ ] postgres
[ ] sqlite
[ ] sqljs
[ ] react-native
[ ] expo

TypeORM version:

[X] latest
[ ] @next
[ ] 0.x.x (or put your version here)

Steps to reproduce or a small repository showing the problem:

I have two entities, Person and Photo which has a one-to-one relationship. After creating a person I'm trying to create a Photo in the @AfterInsert part. However, when trying to fetch the id of the newly created person, it returns undefined (

export class Person {

  @AfterInsert()

  public async handleAfterInsert() {
    const person = await getConnection()
      .getRepository(Person)                     //<--- This is where the problem is
      .findOne(this.id);

    //Insert into Photo
      const photo = New Photo();
      photo.person = person;

    await getConnection()
      .getRepository(Photo)
      .save(photo);
  }

  @PrimaryGeneratedColumn()
  public id: number;

  @OneToOne(type => Photo, photo => photo.person)
  public photo: Photo
}
`
@alex5207 alex5207 changed the title Retrieving in @AfterInsert operation Retrieving ID in @AfterInsert operation Feb 3, 2019
@vlapo
Copy link
Contributor

vlapo commented Feb 3, 2019

Did you use save() or insert() method? Because insert() method is just simple INSERT in DB and save method do lot of magic around - like fill primary generated column.

@alex5207
Copy link
Author

alex5207 commented Feb 3, 2019

@vlapo When creating a Person I am using the save() method.
Note: I can verify that the ID is present if I do a console.log(this.id).

So, its like the repository is not updated quickly enough

@vlapo
Copy link
Contributor

vlapo commented Feb 3, 2019

Understand now. I thought this.id is undefined before. This is problem of transactions. Insert statement is done but transaction is not committed yet so person is not available in new select.

But I do not understand why you need select person again? You have your entity in this so use it.

@AfterInsert()
public async handleAfterInsert() {
    //Insert into Photo
    const photo = New Photo();
    photo.person = this;

    await getConnection()
      .getRepository(Photo)
      .save(photo);
}

@alex5207
Copy link
Author

alex5207 commented Feb 3, 2019

@vlapo I see what you mean. When I just set photo.person = this i get an ER_LOCK_WAIT_TIMEOUT: Lock wait timeout exceeded; try restarting transaction +54168ms

Not sure why that's not working...

@vlapo
Copy link
Contributor

vlapo commented Feb 3, 2019

Yeah you need use same entityManager instance because of transactions. In short you have to use subscriber instead of listener.

@EventSubscriber()
export class PersonSubscriber implements EntitySubscriberInterface<Person> {

    listenTo() {
        return Person;
    }

    async afterInsert(event: InsertEvent<Person>) {
        const photo = new Photo();
        photo.person = event.entity;

        await event.manager
            .getRepository(Photo)
            .save(photo);
    }
}

More info: #743 and #1705 (comment)

@alex5207
Copy link
Author

alex5207 commented Feb 4, 2019

@vlapo - Thanks a lot for your example. Forgive me, but I somehow still cannot get this to work.
I have implemented exactly as in your example in a seperate file from the Person entity.

Nothing really happens when I insert a new Person. I tried doing a console.log('inserted person') inside afterInsert to try and verify whether anything was happening. Nothing came from it.

I tried to read [https://github.com/typeorm/typeorm/blob/master/docs/listeners-and-subscribers.md#what-is-a-subscriber] as well. Seems to provide almost an identical example to yours.

Do I need to create an instance of this class anywhere, or?

Thanks for your patience
BR

@vlapo
Copy link
Contributor

vlapo commented Feb 4, 2019

You have to define subscribers in your connection options. Check this http://typeorm.io/#/connection-options, option subscribers.

I am really suprised we do not have any note about this option in https://github.com/typeorm/typeorm/blob/master/docs/listeners-and-subscribers.md.

@alex5207
Copy link
Author

alex5207 commented Feb 5, 2019

Worked like a charm - Thanks a lot @vlapo

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

No branches or pull requests

2 participants