Domanda

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

Penso che sia abbastanza chiaro quello che sto cercando di fare.Mi aspetto che la persona @ManyToOne venga ereditata dalla classe UglyProblem.Ma ci sarà un'eccezione che dice qualcosa del tipo:"Non è stata trovata alcuna proprietà di questo tipo nella classe UglyProblem (mappedBy="person")".

Tutto quello che ho trovato è Questo.Non sono riuscito a trovare il post di Emmanuel Bernard che spiega le ragioni di ciò.


Sfortunatamente, secondo la documentazione di Hibernate "Le proprietà delle superclassi non mappate come @MappedSuperclass vengono ignorate."

Beh, penso che questo significhi che se ho queste due classi:

public class A {
    private int foo;
}

@Entity
public class B extens A {
}

poi campo foo non verrà mappato per la classe B.Il che ha senso.Ma se ho qualcosa del genere:

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

Mi aspetto che la classe UglyProblem abbia dei file id E name ed entrambe le classi devono essere mappate utilizzando la stessa tabella.(In effetti, questo è esattamente ciò che accade, ho appena controllato di nuovo).Ho questa tabella:

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;

Tornando alla mia domanda:

Mi aspetto che la persona @ManyToOne venga ereditata dalla classe UglyProblem.

Me lo aspetto perché tutti gli altri campi mappati vengono ereditati e non vedo alcun motivo per fare questa eccezione per le relazioni ManyToOne.


Sì, l'ho visto.In effetti, ho utilizzato la soluzione di sola lettura per il mio caso.Ma la mia domanda era "Perché..." :).So che c'è una spiegazione data da un membro del team di ibernazione.Non sono riuscito a trovarlo ed è per questo che ho chiesto.

Voglio scoprire la motivazione di questa decisione progettuale.

(se sei interessato a come ho affrontato questo problema:Ho ereditato un progetto creato utilizzando Hibernate 3.Era Jboss 4.0. Qualcosa + l'ibernazione c'era già (lo scaricavi tutto insieme).Stavo spostando questo progetto su Jboss 4.2.2 e ho scoperto che ci sono mappature ereditate di "@OneToMany mappedBy" e funzionava bene sulla vecchia configurazione...)

È stato utile?

Soluzione

Penso che sia una saggia decisione quella presa dal team di Hibernate.Potrebbero essere meno arroganti e chiarire il motivo per cui è stato implementato in questo modo, ma è proprio così che lavorano Emmanuel, Chris e Gavin.:)

Proviamo a capire il problema.Penso che i tuoi concetti "mentiscano".Prima dici così tanti Problemasono associati a Persone.Ma poi dici quello Persona avere molti Brutto problemas (e non si riferisce ad altri ProblemaS).Qualcosa non va in quel design.

Immagina come verrà mappato nel database.Hai un'ereditarietà di tabella singola, quindi:

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

In che modo l'ibernazione imporrà il database da creare Problema riguardano solo Persone se è problemType è uguale SU?Questo è un problema molto difficile da risolvere.Quindi, se vuoi questo tipo di relazione, ogni sottoclasse deve trovarsi nella propria tabella.Questo è ciò che @MappedSuperclass fa.

P.S.:Ci scusiamo per il brutto disegno :D

Altri suggerimenti

Nel mio caso volevo utilizzare il tipo di ereditarietà SINGLE_TABLE, quindi utilizzare @MappedSuperclass non era un'opzione.

Ciò che funziona, anche se non molto pulito, è aggiungere il proprietario Hibernate @Dove clausola all'associazione @OneToMany per forzare il tipo nelle query:

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

Sfortunatamente, secondo Hibernate documentazione "Le proprietà delle superclassi non mappate come @mapsuperclass vengono ignorate." Ho corso anche contro questo.La mia soluzione era rappresentare l'ereditarietà desiderata attraverso le interfacce anziché gli stessi bean di entità.

Nel tuo caso, potresti definire quanto segue:

public interface Problem {
    public Person getPerson();
}

public interface UglyProblem extends Problem {
}

Quindi implementa queste interfacce utilizzando una superclasse astratta e due sottoclassi di 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 {
}

Come ulteriore vantaggio, se si codifica utilizzando le interfacce anziché gli effettivi bean di entità che implementano tali interfacce, sarà più semplice modificare le mappature sottostanti in un secondo momento (meno rischi di interrompere la compatibilità).

Penso che tu debba annotare il tuo Problema superclasse con @MappedSuperclass invece di @Entità.

Ho capito come risolvere il problema OneToMany mappedBy.

Nella classe derivata UglyProblem dal post originale.Il metodo di callback deve trovarsi nella classe derivata e non nella classe genitore.

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

Ho trovato almeno la salsa segreta per usare Hibernate. http://docs.jboss.org/hibernate/stable/annotations/api/org/hibernate/annotations/ForceDiscriminator.html @ForceDiscriminator fa sì che @OneToMany onori il discriminatore

Richiede annotazioni di ibernazione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top