19

I tienen un compuesto Primary Key (IDHOLIDAYPACKAGE, IDHOLIDAYPACKAGEVARIANT) en la tabla HolidayPackageVariant donde IDHOLIDAYPACKAGE se refiere a entidad HolidayPackage con un Muchos a Una relación entre HolidayPackageVariant y HolidayPackage.¿Por qué mi EmbeddedId en hibernación no funciona?

Cuando trato de hacer el mapeo del compund PK en HolidayPackageVariant, me sale el siguiente error:

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

Puede alguien por favor dígame ¿qué estoy haciendo mal aquí?

MIS POJOs este aspecto:

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

Hola @brainydexter, ¿Podrías por favor cambiar la respuesta correcta a esta pregunta? Tuve que arreglarlo y luego volver aquí y publicar la respuesta solo para darme cuenta de que ya estaba allí. – coderatchet

+1

@coderatchet hecho. Gracias por mencionarlo. Ya no estoy hibernando, así que esto se me cayó de mi radar. – brainydexter

Respuesta

77

No debe tener el @Id en la clase EmbeddedId. Elimine la anotación Id en su HolidayPackageVariantPrimaryKey y debería funcionar bien.

+4

Esto solucionó mi problema también. Creo que esto debería marcarse como la respuesta en lugar de la anterior. – Jalpesh

+2

Parece que esta es la respuesta correcta –

+0

Pero, ¿qué haría? P. si quiero que un miembro 'Id. largo privado;' en mi '@ Integrado' para obtener un valor automático cada vez que inserte un elemento? Esto es [lo que no estoy obteniendo] (http://stackoverflow.com/questions/29976363/hibernate-generatedvalue-in-embedded-always-null) ... – displayname

2

He luchado una vez con @EmbeddedId, y he terminado de lograr el mismo objetivo con @IdClass. La diferencia es que cuando usa @IdClass, no lo usa en la definición de clase, pero redeclara los mismos campos (sin embargo, tengo getters/setters directos para campos id, lo cual es más cómodo para mí).

Aquí está mi ejemplo, a partir del proyecto que utilizo para procesar la base de datos de direcciones disponibles libremente en polaco GUS institución gubernamental:

La clave compuesta:

@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 clase de usarlo (condado):

@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 clase componer clave compuesta (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

No entiendo por qué debería uno usar IdClass ya que necesito redefinir los mismos campos en la clase. Esperaba que funcionara con EmbeddedId – brainydexter

0

Aplicado a un campo persistente o propiedad de una clase de entidad o superclase mapeada para denotar una clave primaria compuesta que es una clase incrustable. La clase incrustable debe anotarse como Embeddable. Debe haber solo una anotación EmbeddedId y ninguna anotación Id cuando se utiliza la anotación EmbeddedId.

La anotación AttributeOverride se puede utilizar para anular las asignaciones de columnas declaradas dentro de la clase incorporable.

La anotación MapsId se puede usar junto con la anotación EmbeddedId para especificar una clave primaria derivada.

Si la entidad tiene una clave principal derivada, la anotación AttributeOverride solo se puede utilizar para anular los atributos de la identificación incrustada que no se corresponden con la relación con la entidad padre.

Cuestiones relacionadas