19

mam związek Primary Key (IDHOLIDAYPACKAGE, IDHOLIDAYPACKAGEVARIANT) w tabeli HolidayPackageVariant gdzie IDHOLIDAYPACKAGE odnosi się do podmiotu HolidayPackage z Wiele do Jeden relacji między HolidayPackageVariant i HolidayPackage.Dlaczego mój embeddedId w stanie hibernacji nie działa?

Kiedy próbuję zrobić mapowanie PK compund w HolidayPackageVariant, pojawia się następujący błąd:

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

Czy ktoś mógłby mi powiedzieć co robię źle tutaj?

MY POJOs wyglądać następująco:

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

Witam na stronie @brainydexter, czy możesz zmienić poprawną odpowiedź na to pytanie? Musiałem to naprawić, a potem wrócić i opublikować odpowiedź, aby zdać sobie sprawę, że już tam jest. – coderatchet

+1

@ coderatchet done. Dziękuję za wskazanie. Nie robiłem już rzeczy hibernacji, więc to spadło z mojego radaru. – brainydexter

Odpowiedz

77

Nie powinieneś mieć klasy @Id w klasie EmbeddedId. Usuń adnotację Id w swoim HolidayPackageVariantPrimaryKey i powinna działać poprawnie.

+4

Naprawiłem też mój problem. Myślę, że powinno to być oznaczone jako odpowiedź zamiast poprzedniej. – Jalpesh

+2

Wygląda na to, że jest to właściwa odpowiedź. –

+0

Ale co powinienem zrobić, np. jeśli chcę, aby element 'private Long id;' w moim '@ Embedded' uzyskał wartość automatyczną za każdym razem, gdy wstawiam element? To jest [czego nie dostaję] (http://stackoverflow.com/questions/29976363/hibernate-generatedvalue-in-embedded-always-null) ... – displayname

2

Walczyłem kiedyś z @EmbeddedId i skończę osiągnięcia tego samego celu z @IdClass. Różnica polega na tym, że gdy używasz @IdClass, nie używasz go w definicji klasy, ale redeclare te same pola (jednak mam następnie bezpośrednie getters/setters dla pól id, co jest dla mnie bardziej wygodne).

Oto mój przykład, od projektu używam przetwarzać swobodnie dostępną bazę adresową z polskiego GUS instytucji rządowych:

Kluczem kompozytowe:

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

Klasa używając go (hrabstwo):

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

Klasa komponowania klucz kompozytowego (prowincja):

@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

Nie rozumiem, dlaczego należy używać IdClass, ponieważ muszę ponownie zdefiniować te same pola w klasie. Miałem nadzieję, że zadziała to z EmbeddedId – brainydexter

0

Stosowane do trwałego pola lub właściwości klasy encji lub odwzorowanej superklasy w celu oznaczenia złożonego klucza podstawowego, który jest klasą do osadzania. Klasa embedable musi być opisana jako Embedable. Występuje tylko jedna adnotacja EmbeddedId i brak adnotacji Id, gdy używana jest adnotacja EmbeddedId.

Adnotacja AttributeOverride może być używana do nadpisania mapowań kolumn zadeklarowanych w klasie embedable.

Adnotacja MapsId może być używana w powiązaniu z adnotacją EmbeddedId w celu określenia pochodnego klucza podstawowego.

Jeśli jednostka ma wyprowadzony klucz podstawowy, adnotacja AttributeOverride może być używana wyłącznie do nadpisania atrybutów identyfikatora wbudowanego, które nie odpowiadają relacji z jednostką nadrzędną.

Powiązane problemy