Frage

Ich versuche, eine Benutzer-zu-Benutzer-Beziehung zu entwerfen, z. B. "Benutzer A folgt Benutzer B" und "Benutzer A möchte der Freund von Benutzer B sein".

Ich habe eine Benutzerklasse und die Art und Weise, wie sie entworfen wurde, sieht folgendermaßen aus:

@Entity
public class User{
    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
    List<User> followers;
    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
    List<User> following;
    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
    List<User> friendRequests;
    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
    List<User> requesting;
    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
    List<User> friends;

}

Ich habe zwei Probleme:

  • Der Ruhezustand gibt mir kann nicht mehrere Taschen gleichzeitig abrufen Problem
  • Ich habe online nachgeschlagen, Leute haben gesagt, sie sollen FetchType.EAGER entfernen oder in Set anstelle von List ändern, aber das hat dazu geführt, dass Feld keinen Standardwert hat

    Ich habe das Gefühl, dass die Beziehung nicht richtig definiert ist, und ich sollte auch mehr Tabellen sehen, da ich momentan nur die Benutzertabelle und die Benutzertabelle sehe.


    Update

    Im Folgenden werden 3 Tabellen, Freunde, Follower und Anforderer erstellt. Ist das im Vergleich zu 5 Tabellen etwas optimiert? Und gibt es einen Vorteil gegenüber dem, was Mr. J4mes vorgeschlagen hat?

    @ManyToMany
    @JoinTable(name = "followers", joinColumns = @JoinColumn(name = "followerId"), inverseJoinColumns = @JoinColumn(name = "userId"))
    private List<User> followers;
    @ManyToMany
    @JoinTable(name = "followers", joinColumns = @JoinColumn(name = "userId"), inverseJoinColumns = @JoinColumn(name = "followerId"))
    private List<User> following;
    @ManyToMany
    @JoinTable(name = "friends", joinColumns = @JoinColumn(name = "userId"), inverseJoinColumns = @JoinColumn(name = "friendId"))
    private List<User> friends;
    @ManyToMany
    @JoinTable(name = "requesters", joinColumns = @JoinColumn(name = "requesterId"), inverseJoinColumns = @JoinColumn(name = "userId"))
    private List<User> friendRequests;
    @ManyToMany
    @JoinTable(name = "requesters", joinColumns = @JoinColumn(name = "userId"), inverseJoinColumns = @JoinColumn(name = "requesterId"))
    private List<User> requesting;
    

War es hilfreich?

Lösung

Um Ihre Funktion zu implementieren, sollten Sie zunächst @ManyToMany anstelle von @OneToMany verwenden.Es sollte so aussehen:

@Entity
public class User implements Serializable {
   @ManyToMany(mappedBy="followers")
   @JoinTable(name="followingTable")
   private Set<User> following;
   @ManyToMany
   @JoinTable(name="followerTable")
   private Set<User> followers;
   @ManyToMany(mappedBy="friendRequests")
   @JoinTable(name="requestingTable")
   private Set<User> requesting;
   @ManyToMany
   @JoinTable(name="friendRequestTable")
   private Set<User> friendRequests;
   @ManyToMany
   private Set<User> friends;
}

Ihre Beziehungen sehen für mich wie bidirektionale aus.Wenn Sie @OneToMany verwenden, bedeutet dies, dass C has 2 followers A and B= A and B only follows C.Tatsache ist jedoch, dass eine Person vielen Menschen folgen kann und eine Person von vielen Menschen verfolgt werden kann.Mit anderen Worten, A and B can also follow D.

Außerdem sollten Sie cascadeType.ALL überhaupt nicht verwenden.Diese Kaskadenrichtlinie bedeutet, dass, wenn ein Benutzer sein Konto löscht und Sie den entsprechenden Eintrag in der Datenbank löschen, auch alle seine Freunde usw. gelöscht werden.

Andere Tipps

Der Ruhezustand generiert nur eine Tabelle für die Benutzerentität, und ich gehe von einer Querverweistabelle für die Benutzer-zu-Benutzer-Beziehung aus.Problemumgehung für unterschiedliche Tabellen kann darin bestehen, dass unterschiedliche Entitäten für die unterschiedlichen Beziehungen eingerichtet werden, d. H.

Benutzerentität

@OneToMany
List<Follower> followers;

Follower-Entität

@Entity
class Follower
...
@ManyToOne
User user;

@Id
@Generated
int id;

Was das Abrufen von EAGER betrifft, möchten Sie möglicherweise, dass alle diese Daten faul sind, da je nach Einrichtung Ihrer Datenbank all diese eifrigen Ladevorgänge sehr teuer sein können.Nur wenn der Benutzer die Follower des Benutzers laden möchte, möchte ich sie abrufen.

Trennen Sie den User vom Friends. Versuchen Sie, eine Tabelle mit mindestens 2 Spalten zu erstellen, die den User_ID auf alle seine Friends_IDss abbildet, die im Grunde genommen auf den User_ID verweisen

Auch EAGER lädt ALLE die Daten, sobald Sie sie zum ersten Mal aufrufen.Bedeutet, dass alle Benutzer und ihre Freunde geladen werden.Das Laden von Freunden sollte LAZY sein, d. H. Nur geladen, wenn Sie sie benötigen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top