19

Ho un composto chiave primaria (IDHOLIDAYPACKAGE, IDHOLIDAYPACKAGEVARIANT) nella tabella HolidayPackageVariant dove IDHOLIDAYPACKAGE si riferisce a entità HolidayPackage con un Molti a One rapporto tra HolidayPackageVariant e HolidayPackage.Perché il mio EmbeddedId in ibernazione non funziona?

Quando provo a fare la mappatura PK compund in HolidayPackageVariant, ottengo il seguente errore:

Initial SessionFactory creation failed.org.hibernate.annotations.common.AssertionFailure: Declaring class is not found in the inheritance state hierarchy: org.wah.model.holidaypackage.HolidayPackageVariantPrimaryKey

Qualcuno può dirmi che cosa sto facendo male qui?

MIEI POJO simile a questa:

HolidayPackageVariant:

@Entity 
@Table(name="HOLIDAYPACKAGEVARIANT") 
public final class HolidayPackageVariant { 

    private HolidayPackageVariantPrimaryKey idCompound; 

    @EmbeddedId 
    public HolidayPackageVariantPrimaryKey getIdCompound() { 
     return idCompound; 
    } 

    // other code 
} 

HolidayPackageVariantPrimaryKey

@Embeddable 
public final class HolidayPackageVariantPrimaryKey implements Serializable { 

    private Integer idHolidayPackageVariant; 
    private HolidayPackage holidayPackage; 

    public HolidayPackageVariantPrimaryKey(){} 

    public HolidayPackageVariantPrimaryKey(int id, HolidayPackage pkg){ 
     setIdHolidayPackageVariant(id); 
     setHolidayPackage(pkg); 
    } 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Column(name = "IDHOLIDAYPACKAGEVARIANT", nullable = false) 
    public Integer getIdHolidayPackageVariant() { 
     return idHolidayPackageVariant; 
    } 

    @Id 
    @ManyToOne(fetch=FetchType.LAZY, cascade={CascadeType.ALL}) 
    @JoinColumn(name="IDHOLIDAYPACKAGE", nullable=false) 
    public HolidayPackage getHolidayPackage() { 
     return holidayPackage; 
    } 

    // equals and hashCode 
} 

HolidayPackage

public final class HolidayPackage { 
    private Set<HolidayPackageVariant> holidayPackageVariants = new HashSet<HolidayPackageVariant>(0); 

    @OneToMany(fetch=FetchType.LAZY, cascade={CascadeType.ALL}, mappedBy = "idCompound.holidayPackage") 
    public Set<HolidayPackageVariant> getHolidayPackageVariants() { 
     return holidayPackageVariants; 
    } 

    // other code 
} 
+0

Ciao @brainydexter, Potresti cambiare la risposta corretta a questa domanda? Ho dovuto sistemarlo e tornare qui e pubblicare la risposta solo per capire che era già lì. – coderatchet

+1

@coderatchet fatto. Grazie per segnalarlo. Non fare più cose in letargo, quindi questo è caduto dal mio radar. – brainydexter

risposta

77

Non si dovrebbe avere il @Id nella classe EmbeddedId. Rimuovi l'annotazione Id nel tuo HolidayPackageVariantPrimaryKey e dovrebbe funzionare correttamente.

+4

Questo ha risolto anche il mio problema. Penso che questo dovrebbe essere contrassegnato come la risposta al posto del precedente. – Jalpesh

+2

Sembra che questa sia la risposta giusta –

+0

Ma cosa dovrei fare ad es. se desidero un membro 'ID lungo privato' nel mio '@ Embedded 'per ottenere un valore automatico ogni volta che inserisco un elemento? Questo è [ciò che non sto ottenendo] (http://stackoverflow.com/questions/29976363/hibernate-generatedvalue-in-embedded-always-null) ... – displayname

2

Ho combattuto una volta con @EmbeddedId, e ho finito raggiungere lo stesso obiettivo con @IdClass. La differenza è che quando si usa @IdClass, non lo si usa nella definizione della classe, ma si redeclare gli stessi campi (tuttavia, ho diretto getter/setter per i campi id, che è più comodo per me).

Ecco il mio esempio, dal progetto che uso per elaborare database di indirizzi liberamente disponibile dal polacco istituzione governativa GUS:

La chiave composta:

@Embeddable 
class GusPowiatPK implements Serializable { 
    private static final long serialVersionUID = 1L; 
    private Short powiatNr; 
    private GusWojewodztwo wojewodztwo; 

    @Column(name = "POW_NR") 
    public Short getPowiatNr() { 
     return powiatNr; 
    } 

    public void setPowiatNr(Short powiatNr) { 
     this.powiatNr = powiatNr; 
    } 

    @ManyToOne 
    @JoinColumn(name = "WOJ_ID") 
    public GusWojewodztwo getWojewodztwo() { 
     return wojewodztwo; 
    } 

    public void setWojewodztwo(GusWojewodztwo wojewodztwo) { 
     this.wojewodztwo = wojewodztwo; 
    } 
} 

La classe di usarlo (contea):

@Entity 
@Table(name = "POWIAT") 
@IdClass(GusPowiatPK.class) 
public class GusPowiat { 

    private Short powiatNr; 
    private GusWojewodztwo wojewodztwo; 
    private String nazwa; 
    private Date stanNa; 
    private boolean powiatMiejski; 

    public GusPowiat() { 
     super(); 
    } 

    public GusPowiat(Short powiatNr, GusWojewodztwo wojewodztwo) { 
     super(); 
     this.powiatNr = powiatNr; 
     this.wojewodztwo = wojewodztwo; 
    } 

    @Id 
    public Short getPowiatNr() { 
     return powiatNr; 
    } 

    public void setPowiatNr(Short powiatNr) { 
     this.powiatNr = powiatNr; 
    } 

    @Id 
    public GusWojewodztwo getWojewodztwo() { 
     return wojewodztwo; 
    } 

    public void setWojewodztwo(GusWojewodztwo wojewodztwo) { 
     this.wojewodztwo = wojewodztwo; 
    } 

    @Column(name = "NAZWA", length = 50, nullable = false) 
    public String getNazwa() { 
     return nazwa; 
    } 

    public void setNazwa(String nazwa) { 
     this.nazwa = nazwa; 
    } 

    @Temporal(TemporalType.DATE) 
    @Column(name = "STAN_NA", nullable = false) 
    public Date getStanNa() { 
     return stanNa; 
    } 

    public void setStanNa(Date stanNa) { 
     this.stanNa = stanNa; 
    } 

    @Column(name = "POW_MIEJSKI") 
    public boolean isPowiatMiejski() { 
     return powiatMiejski; 
    } 

    public void setPowiatMiejski(boolean powiatMiejski) { 
     this.powiatMiejski = powiatMiejski; 
    } 
} 

La classe comporre chiave composta (provincia):

@Entity 
@Table(name = "WOJEWODZTWO") 
public class GusWojewodztwo { 

    private Short id; 
    private String nazwa; 
    private Date stanNa; 

    public GusWojewodztwo() { 
     super(); 
    } 

    public GusWojewodztwo(Short id) { 
     super(); 
     this.id = id; 
    } 

    @Id 
    @Column(name = "WOJ_ID") 
    public Short getId() { 
     return id; 
    } 

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

    @Column(name = "NAZWA", length = 50, nullable = false) 
    public String getNazwa() { 
     return nazwa; 
    } 

    public void setNazwa(String nazwa) { 
     this.nazwa = nazwa; 
    } 

    @Temporal(TemporalType.DATE) 
    @Column(name = "STAN_NA", nullable = false) 
    public Date getStanNa() { 
     return stanNa; 
    } 

    public void setStanNa(Date stanNa) { 
     this.stanNa = stanNa; 
    } 
} 
+0

Non capisco perché si dovrebbe usare IdClass poiché ho bisogno di ridefinire gli stessi campi nella classe. Speravo di farlo funzionare con EmbeddedId – brainydexter

0

Applicato a un campo o proprietà persistente di una classe entità o superclasse mappata per indicare una chiave primaria composta che è una classe incorporabile. La classe incorporabile deve essere annotata come Embeddable. Deve essere presente solo un'annotazione EmbeddedId e nessuna annotazione Id quando si utilizza l'annotazione EmbeddedId.

L'annotazione AttributeOverride può essere utilizzata per sovrascrivere i mapping di colonne dichiarati all'interno della classe incorporabile.

L'annotazione MapsId può essere utilizzata insieme all'annotazione EmbeddedId per specificare una chiave primaria derivata.

Se l'entità ha una chiave primaria derivata, l'annotazione AttributeOverride può essere utilizzata solo per sovrascrivere quegli attributi dell'ID incorporato che non corrispondono alla relazione con l'entità padre.

Problemi correlati