web-dev-qa-db-fra.com

JPA OneToMany et ManyToOne projection: colonne répétée dans le mappage pour la colonne entity (doit être mappée avec insert = "false" update = "false")

J'ai trois classes dont le nom est User et cet utilisateur possède d'autres instances de classes. Comme ça;

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;
 }

ça marche comme ça mais génère des tables emty en db. Qui doivent contenir des clés étrangères. Lorsque j'ai essayé d'utiliser mappedBy et JoinColumn annotains, j'ai échoué. Comment puis-je résoudre ça?

informations supplémentaires:

Quand j'ai changé avec;

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

et

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

Je suis en train

Une erreur JPA s'est produite (impossible de créer EntityManagerFactory): colonne répétée dans le mappage pour l'entité: models.post.APost colonne: id (doit être mappée avec insert = "false" update = "false")

Final Edit: Enfin, je me suis totalement trompé à propos de jpa annotaions. :( Quand je change

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

à

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

et

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

tout fonctionne bien. :)

49
Ömer Faruk AK

Comme je l'ai expliqué dans cet article et dans mon livre, High-Performance Java Persistence =, vous ne devez jamais utiliser le paramètre unidirectionnel @OneToMany annotation parce que:

  1. Il génère des instructions SQL inefficaces
  2. Il crée une table supplémentaire qui augmente l'encombrement de la mémoire de vos index de base de données.

Maintenant, dans votre premier exemple, les deux côtés possèdent l'association et c'est mauvais .

Tandis que le @JoinColumn laisserait le @OneToMany responsable de l’association, ce n’est certainement pas le meilleur choix. Par conséquent, utilisez toujours l'attribut mappedBy sur le @OneToMany côté.

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

Je ne suis pas vraiment sûr de votre question (la signification de "table vide", etc., ou comment mappedBy et JoinColumn ne fonctionnaient pas).

Je pense que vous essayiez de faire une relation bidirectionnelle.

Premièrement, vous devez décider de quel côté "appartient" la relation. Hibernate va configurer la base de relation de ce côté. Par exemple, supposons que la relation soit attribuée au côté Post (je simplifie votre exemple, pour que les choses restent claires), le mappage ressemblera à ceci:

(Je souhaite que la syntaxe soit correcte. Je les écris simplement par mémoire. Cependant, l'idée devrait bien se passer)

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;
}

Ce faisant, la table pour Post aura une colonne user_id qui stocke la relation. Hibernate obtient la relation par le user dans Post (au lieu de posts dans User. Vous remarquerez la différence si vous avez Post's user mais il manque _ Userposts).

Vous avez mentionné que mappedBy et JoinColumn ne fonctionnaient pas. Cependant, je crois que c'est en fait la bonne façon. Veuillez indiquer si cette approche ne fonctionne pas pour vous et donnez-nous un peu plus d'informations sur le problème. Je crois que le problème est dû à autre chose.


Modifier:

Juste un peu d’informations supplémentaires sur l’utilisation de mappedBy car cela prête généralement à confusion au début. Dans mappedBy, nous plaçons le "nom de la propriété" dans le côté opposé de la relation bidirectionnelle, pas le nom de la colonne de la table.

65
Adrian Shum