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

Non-owning relationship fields in entity types #24653

Closed
1 task done
emilpaw opened this issue Dec 22, 2023 · 5 comments · Fixed by #25007 or #25065
Closed
1 task done

Non-owning relationship fields in entity types #24653

emilpaw opened this issue Dec 22, 2023 · 5 comments · Fixed by #25007 or #25065

Comments

@emilpaw
Copy link
Contributor

emilpaw commented Dec 22, 2023

Overview of the feature request

In PR #19098 the Angular entity model template was changed so that only fields are included for related entities if the entity is on the owning side. For React and Vue it still showed fields for all relationships.

I assumed only the owning side relationships to be shown to be the correct behavior, and that it was just not changed for React and Vue yet.

But recently in 52aad30 it was changed back to also include non-owning side relationships.

That makes me wonder if entity types should actually include non-owning side relationships or not.

e.g. JDL like following:

entity EntityA
entity EntityB

relationship OneToMany {
    EntityA to EntityB
}

generates following types (example generated using Angular, but it's similar for React and Vue):

export interface IEntityA {
  id: number;
  entityBS?: IEntityB[] | null;
}
export interface IEntityB {
  id: number;
  entityA?: IEntityA | null;
}

This might make one think that it's possible to create or retrieve EntityA with EntityB's attached, but that is in fact not possible. This was the root issue that caused confusion and resulted in #19780.

My proposal is to only include fields that can actually be used in the entity types as it was done in #19098 for Angular and to make this behavior consistent across client frameworks.
But I might be missing a use case for why non-owning side relationship fields must be present in the entity types, and I am eager to hear your thoughts.

Motivation for or Use Case

TypeScript types are more useful if they precisely describe the actual JavaScript objects. A mismatch can cause confusion and lead to bugs.

Related issues or PR
@mshima
Copy link
Member

mshima commented Dec 24, 2023

Owner side is a not concept that should be applied to every database. But prior to v8 it was applied to jdl, so it was applied to the entire JHipster.
IMO it’s not the right approach.
For example:

  1. relationship OneToOne { A to B }
  2. relationship OneToMany { A to B }
  3. relationship ManyToOne { A to B }
  4. relationship ManyToMany { A to B }

In every relationship, except example 2, the owner side is the left.
JHipster sql implementation does not support OneToMany relationships so it’s inverted to be a ManyToOne relationship.
Neo4j implementation on the other hand supports OneToMany relationships.

Design that can be changed (enhancements):

  1. OneToMany relationship support can be added using join table
  2. ManyToMany relationship does not have a owner side.

This was partially explained in #24076

You can accomplish the desired behavior by converting the bidirectional OneToMany relationship to a unidirectional ManyToOne relationship.
From (bidirectional OneToMany)

relationship OneToMany {
    EntityA to EntityB
}

To (unidirectional ManyToOne):

relationship ManyToOne {
    EntityB{entityA} to EntityA
}

@emilpaw
Copy link
Contributor Author

emilpaw commented Dec 24, 2023

Thanks for explaining @mshima, but I am aware about how the relationships work. In this issue, I wanted to discuss how the relationships are represented in the TypeScript types, as I think they might be improved. Regardless of how the relationships are implemented, the API should be described as precisely as possible.

Or are these topics intertwined and have to be thought out together?

@mshima
Copy link
Member

mshima commented Dec 25, 2023

See #24350.
When using Neo4j the entire graph with every relationship is fetched from db, passed to fronted, sent to backend, and persisted.
Every relationship is writable, the typescript model is correct.

We could add a property to hide from types, but I wonder if it’s worth.

@emilpaw
Copy link
Contributor Author

emilpaw commented Dec 26, 2023

So in other words, the issue is that for some backend options the capabilities of the API change and relationships may or may not be provided.

What exactly do you mean by adding a property? In the templates for the type generation?

I figure that changing frontend types depending on backend options would introduce complexity and be a maintance burden. Considering this I am also not sure if it's worth it.

@mshima
Copy link
Member

mshima commented Dec 27, 2023

We do have an option to manually eager load a relationship https://github.com/jhipster/generator-jhipster/blob/main/generators/app/README.md#eager-loading-relationships.
So I suppose we can write relationships on models based on persistableRelationship and relationshipEagerLoad properties.

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