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

belongsToMany relation to model of the same type fails #2118

Closed
hvlawren opened this issue Dec 4, 2018 · 8 comments
Closed

belongsToMany relation to model of the same type fails #2118

hvlawren opened this issue Dec 4, 2018 · 8 comments
Labels
Docs good first issue Relations Model relations (has many, etc.)

Comments

@hvlawren
Copy link

hvlawren commented Dec 4, 2018

From discussion on #1571

Description

I have a model called Category with a parentId field that points to the parent Category

Category Model:

export class Category extends Entity {
  @property({
    type: 'number',
    id: true,
    generated: true
  })
  id?: number;

  @belongsTo(() => Category)
  parentId: number;

  @belongsTo(() => Domain)
  containerId: number;

  @property({
    type: 'boolean',
    default: false,
  })
  internal?: boolean;

  @property({
    type: 'string',
    required: true,
  })
  title: string;

  @property({
    type: 'string',
  })
  description?: string;

  @property({
    type: 'string',
  })
  state?: string;

  constructor(data?: Partial<Category>) {
    super(data);
  }
}

I created a /categories/{id}/parent endpoint per the docs

When I call that endpoint I get this error:

Unhandled error in GET /categories/2/parent: 500 Error: Circular dependency detected: controllers.CategoryParentController --> @CategoryParentController.constructor[0] --> repositories.CategoryRepository --> @CategoryRepository.constructor[2] --> repositories.CategoryRepository

Category Parent Controller:

export class CategoryParentController {
  constructor(@repository(CategoryRepository) protected categoryRepository: CategoryRepository) { }
  @get('/categories/{id}/parent')
  async getCustomer(
    @param.path.number('id') id: number,
  ): Promise<Category> {
    return await this.categoryRepository.parent(id);
  }
}

Category Repository

export class CategoryRepository extends DefaultCrudRepository<
  Category,
  typeof Category.prototype.id
> {
  public readonly container: BelongsToAccessor<Domain, number>;
  public readonly parent: BelongsToAccessor<Category, number>;
  constructor(
    @inject('datasources.db') dataSource: DbDataSource,
    @repository.getter(DomainRepository)
    protected domainRepositoryGetter: Getter<DomainRepository>,
    @repository.getter(CategoryRepository)
    protected categoryRepositoryGetter: Getter<CategoryRepository>
  ) {
    super(Category, dataSource);
    this.container = this._createBelongsToAccessorFor('container', domainRepositoryGetter);
    this.parent = this._createBelongsToAccessorFor('parent', categoryRepositoryGetter);
  }
}

Note that the container part works as expected, only parent is broken.

@bajtos
Copy link
Member

bajtos commented Dec 4, 2018

In your CategoryRepository, you are injecting a getter for obtaining the same repository again.

Since your relation is referring back to the same model, you can reuse the same repository.

Could you please check if the following code fixes to problem for you?

export class CategoryRepository extends DefaultCrudRepository<
  Category,
  typeof Category.prototype.id
> {
  public readonly container: BelongsToAccessor<Domain, number>;
  public readonly parent: BelongsToAccessor<Category, number>;
  constructor(
    @inject('datasources.db') dataSource: DbDataSource,
    @repository.getter(DomainRepository)
    protected domainRepositoryGetter: Getter<DomainRepository>,
  ) {
    super(Category, dataSource);
    this.container = this._createBelongsToAccessorFor('container', domainRepositoryGetter);
    this.parent = this._createBelongsToAccessorFor('parent', Getter.fromValue(this));
  }
}

I think you won't be the last person encountering this issue, let's describe the problem & the solution in our docs, e.g. hasMany relation and belongsTo relation. (Feel free to propose other places where you would be looking for this information.)

Would you @hvlawren like to contribute this documentation change yourself?

@bajtos bajtos added Docs good first issue Relations Model relations (has many, etc.) labels Dec 4, 2018
@hvlawren
Copy link
Author

hvlawren commented Dec 4, 2018

That fixed it!

I'd say those two places probably make the most sense.

I've got a lot on my plate right now, so I'd suggest someone else add the docs.

@bajtos
Copy link
Member

bajtos commented Dec 4, 2018

That fixed it!

Great! 🎉

I'd say those two places probably make the most sense.

I've got a lot on my plate right now, so I'd suggest someone else add the docs.

We all have a lot on our plates, don't we? 😉

It would be great if you could find some time later to contribute back, but I will understand if you don't.

Let's keep this issue open, I think it's a good opportunity for new contributors.

@vvdwivedi
Copy link
Contributor

Well, I am sniffing around for good first issues. Will take this up.

@haotangio
Copy link
Contributor

haotangio commented Dec 26, 2018

Hello.
I made a PR to update document for this issue: #2196
Please help me check it.

@mmeilby
Copy link

mmeilby commented May 25, 2020

I just realized that if the above CategoryRepository has a hasMany relation to DocumentRepository and DocumentRepository has a belongsTo relation to CategoryRepository then you get a circular dependency error.
What should be done in this case as the Getter.fromValue(this) isnt really usefull here?

@SebastianDaehnrich
Copy link

@mmeilby: do you found a solution for the case

@mmeilby
Copy link

mmeilby commented Oct 18, 2020

@mmeilby: do you found a solution for the case

Yes, the solution in May was to add this line before the repository class definition:
@bind({scope: BindingScope.SINGLETON})
export class SomeRepository extends DefaultTransactionalRepository ...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Docs good first issue Relations Model relations (has many, etc.)
Projects
None yet
Development

No branches or pull requests

6 participants