wake-up-neo.com

JPA OneToMany und ManyToOne throw: Wiederholte Spalte in der Zuordnung für Entitätsspalte (sollte mit insert = "false" update = "false" zugeordnet werden)

Ich habe drei Klassen, einer der Namen ist Benutzer und dieser Benutzer hat andere Klasseninstanzen. So was;

public class User{
    @OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL)
    public List<APost> aPosts;

    @OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL)
    public List<BPost> bPosts;
}




   public class BPost extends Post {

    @ManyToOne(fetch=FetchType.LAZY)    
    public User user;
 }

    public class APost extends Post {

     @ManyToOne(fetch=FetchType.LAZY) 
     public User user;
 }

es funktioniert so, erzeugt aber leere Tabellen in db. Welche müssen Fremdschlüssel enthalten. Als ich versucht habe, Annotains von mappedBy und JoinColumn zu verwenden, bin ich gescheitert. Wie kann ich das beheben?

Zusätzliche Informationen:

Als ich mich mit änderte;

 @ManyToOne(fetch=FetchType.LAZY)
 @JoinColumn(name="id")
 public User user;

und

 @OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL, mappedBy="id")
 public List<APost> aPosts;

Ich erhalte

Ein JPA-Fehler ist aufgetreten (EntityManagerFactory kann nicht erstellt werden): Wiederholte Spalte in Zuordnung für Entität: models.post.APost-Spalte: id (sollte mit insert = "false" update = "false" zugeordnet werden)

Final Edit: Endlich habe ich mich in Bezug auf JPA-Annotationen total geirrt. :( Wenn ich mich ändere

@OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL, mappedBy="id")

zu

@OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL, mappedBy="user")

und

@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="user_id")

alles funktioniert ok :)

49
Ömer Faruk AK

Wie ich in diesem Artikel und in meinem Buch High-Performance Java Persistence erklärt habe, sollten Sie niemals das unidirektionale @OneToMany Anmerkung, weil:

  1. Es generiert ineffiziente SQL-Anweisungen
  2. Es wird eine zusätzliche Tabelle erstellt, die den Speicherbedarf Ihrer DB-Indizes erhöht

In Ihrem ersten Beispiel besitzen beide Seiten die Assoziation und das ist schlecht .

Während @JoinColumn würde das @OneToMany Die Seite, die für den Verband verantwortlich ist, ist definitiv nicht die beste Wahl. Verwenden Sie daher immer das mappedBy -Attribut für das @OneToMany Seite.

public class User{
    @OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL, mappedBy="user")
    public List<APost> aPosts;

    @OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL, mappedBy="user")
    public List<BPost> bPosts;
}

public class BPost extends Post {

    @ManyToOne(fetch=FetchType.LAZY)    
    public User user;
}

public class APost extends Post {

     @ManyToOne(fetch=FetchType.LAZY) 
     public User user;
}
28
Vlad Mihalcea

Ich bin mir bei Ihrer Frage nicht sicher (die Bedeutung von "leere Tabelle" usw. oder wie mappedBy und JoinColumn nicht funktionierten).

Ich denke, Sie haben versucht, bidirektionale Beziehungen aufzubauen.

Zunächst müssen Sie entscheiden, welcher Seite die Beziehung "gehört". Hibernate wird die Beziehungsbasis auf dieser Seite einrichten. Angenommen, ich mache die Post - Seite zum Eigentümer der Beziehung (ich vereinfache Ihr Beispiel, um die Dinge auf den Punkt zu bringen), dann sieht die Zuordnung folgendermaßen aus:

(Wünschte, die Syntax wäre korrekt. Ich schreibe sie nur auswendig. Die Idee sollte jedoch in Ordnung sein.)

public class User{
    @OneToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL, mappedBy="user")
    private List<Post> posts;
}


public class Post {
    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="user_id")
    private User user;
}

Auf diese Weise enthält die Tabelle für Post eine Spalte user_id welche die Beziehung speichern. Ruhezustand erhält die Beziehung durch user in Post (anstelle von posts in User. Sie werden den Unterschied bemerken, wenn Sie Post haben. ] ist user, aber es fehlt User ist posts).

Sie haben mappedBy erwähnt und JoinColumn funktioniert nicht. Ich glaube jedoch, dass dies tatsächlich der richtige Weg ist. Bitte teilen Sie uns mit, ob dieser Ansatz bei Ihnen nicht funktioniert, und geben Sie uns ein wenig mehr Informationen zum Problem. Ich glaube, das Problem liegt an etwas anderem.


Bearbeiten:

Nur ein paar zusätzliche Informationen zur Verwendung von mappedBy, da dies normalerweise zunächst verwirrend ist. In mappedBy setzen wir den "Eigenschaftsnamen" auf die entgegengesetzte Seite der bidirektionalen Beziehung und nicht auf den Namen der Tabellenspalte.

65
Adrian Shum