Question

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class Problem {
    @ManyToOne
    private Person person;
}

@Entity
@DiscriminatorValue("UP")
public class UglyProblem extends Problem {}

@Entity
public class Person {
    @OneToMany(mappedBy="person")
    private List< UglyProblem > problems;
}

Je pense que ce que j'essaie de faire est assez clair.Je m'attends à ce que la personne @ManyToOne soit héritée par la classe UglyProblem.Mais il y aura une exception disant quelque chose comme :"Aucune propriété de ce type n'a été trouvée dans la classe UglyProblem (mappedBy="person")".

Tout ce que j'ai trouvé c'est ce.Je n'ai pas pu trouver le message d'Emmanuel Bernard expliquant les raisons de cela.


Malheureusement, selon la documentation Hibernate, "les propriétés des superclasses non mappées comme @MappedSuperclass sont ignorées".

Eh bien, je pense que cela signifie que si j'ai ces deux classes :

public class A {
    private int foo;
}

@Entity
public class B extens A {
}

puis champ foo ne sera pas mappé pour la classe B.Ce qui est logique.Mais si j'ai quelque chose comme ça :

@Entity
public class Problem {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

private String name;

public Long getId() {
    return id;
}

public void setId(Long id) {
    this.id = id;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}
}

@Entity
public class UglyProblem extends Problem {

private int levelOfUgliness;

public int getLevelOfUgliness() {
    return levelOfUgliness;
}

public void setLevelOfUgliness(int levelOfUgliness) {
    this.levelOfUgliness = levelOfUgliness;
}
}

Je m'attends à ce que la classe UglyProblem ait des fichiers id et name et les deux classes doivent être mappées en utilisant la même table.(En fait, c'est exactement ce qui se passe, je viens de revérifier).J'ai ce tableau :

CREATE TABLE "problem" (
    "DTYPE" varchar(31) NOT NULL,
    "id" bigint(20) NOT NULL auto_increment,
    "name" varchar(255) default NULL,
    "levelOfUgliness" int(11) default NULL,
    PRIMARY KEY  ("id")
) AUTO_INCREMENT=2;

Je reviens à ma question :

Je m'attends à ce que la personne @ManyToOne soit héritée par la classe UglyProblem.

Je m'attends à cela parce que tous les autres champs mappés sont hérités et je ne vois aucune raison de faire cette exception pour les relations ManyToOne.


Ouais, j'ai vu ça.En fait, j'ai utilisé la solution en lecture seule pour mon cas.Mais ma question était "Pourquoi..." :).Je sais qu'il y a une explication donnée par un membre de l'équipe hibernate.Je n'ai pas réussi à le trouver et c'est pourquoi j'ai demandé.

Je veux découvrir la motivation de cette décision de conception.

(si vous êtes intéressé par la façon dont j'ai fait face à ce problème :J'ai hérité d'un projet construit avec hibernate 3.C'était Jboss 4.0.quelque chose + mise en veille prolongée était déjà là (vous téléchargeriez tout cela ensemble).Je déplaçais ce projet vers Jboss 4.2.2 et j'ai découvert qu'il existe des mappages hérités de "@OneToMany mappedBy" et cela fonctionnait bien sur l'ancienne configuration...)

Était-ce utile?

La solution

Je pense que c'est une sage décision prise par l'équipe Hibernate.Ils pourraient être moins arrogants et expliquer clairement pourquoi cela a été mis en œuvre de cette façon, mais c'est exactement ainsi que fonctionnent Emmanuel, Chris et Gavin.:)

Essayons de comprendre le problème.Je pense que vos concepts "mentent".D'abord tu dis que beaucoup Problèmes sont associés à Personnes.Mais ensuite tu dis celui-là Personne ont beaucoup LaidProblèmes (et ne concerne pas d'autres Problèmes).Quelque chose ne va pas avec cette conception.

Imaginez comment cela va être mappé à la base de données.Vous disposez d'un seul héritage de table, donc :

          _____________
          |__PROBLEMS__|          |__PEOPLE__|
          |id <PK>     |          |          |
          |person <FK> | -------->|          |
          |problemType |          |_________ |
          -------------- 

Comment hibernate va-t-il appliquer la base de données pour créer Problème ne concernent que Personnes si c'est Type de problème est-ce égal UP ?C'est un problème très difficile à résoudre.Donc, si vous voulez ce type de relation, chaque sous-classe doit être dans sa propre table.C'est ce que @MappedSuperclass fait.

PS. :Désolé pour le dessin moche :D

Autres conseils

Dans mon cas, je voulais utiliser le type d'héritage SINGLE_TABLE, donc utiliser @MappedSuperclass n'était pas une option.

Ce qui fonctionne, même si ce n'est pas très propre, c'est d'ajouter le logiciel propriétaire Hibernate @Où clause à l'association @OneToMany pour forcer le type dans les requêtes :

@OneToMany(mappedBy="person")
@Where(clause="DTYPE='UP'")
private List< UglyProblem > problems;

Malheureusement, selon Hibernate Documentation "Les propriétés des superclasses non cartographiées car @MaptSuperClass sont ignorées." J'ai aussi couru contre cela.Ma solution consistait à représenter l'héritage souhaité via des interfaces plutôt que par les beans entité eux-mêmes.

Dans votre cas, vous pourriez définir les éléments suivants :

public interface Problem {
    public Person getPerson();
}

public interface UglyProblem extends Problem {
}

Implémentez ensuite ces interfaces à l'aide d'une superclasse abstraite et de deux sous-classes d'entité :

@MappedSuperclass
public abstract class AbstractProblemImpl implements Problem {
    @ManyToOne
    private Person person;

    public Person getPerson() {
        return person;
    }
}

@Entity
public class ProblemImpl extends AbstractProblemImpl implements Problem {
}

@Entity
public class UglyProblemImpl extends AbstractProblemImpl implements UglyProblem {
}

Comme avantage supplémentaire, si vous codez en utilisant les interfaces plutôt que les beans d'entité réels qui implémentent ces interfaces, il est plus facile de modifier ultérieurement les mappages sous-jacents (moins de risque de rupture de compatibilité).

Je pense que tu dois annoter ton Problème super classe avec @MappedSuperclass au lieu de @Entité.

J'ai compris comment résoudre le problème OneToMany mappedBy.

Dans la classe dérivée UglyProblem du message d'origine.La méthode de rappel doit se trouver dans la classe dérivée et non dans la classe parent.

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@ForceDiscriminator
public class Problem {

}

@Entity
@DiscriminatorValue("UP")
public class UglyProblem extends Problem {
    @ManyToOne
    private Person person;
}

@Entity
public class Person {
    @OneToMany(mappedBy="person")
    private List< UglyProblem > problems;
}

J'ai au moins trouvé la sauce secrète pour utiliser Hibernate. http://docs.jboss.org/hibernate/stable/annotations/api/org/hibernate/annotations/ForceDiscriminator.html Le @ForceDiscriminator fait que le @OneToMany honore le discriminateur

Nécessite des annotations Hibernate.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top