====== Claves primarias compuestas ======
--- //[[pedrody@um.es|PEDRO DELGADO YARZA]] 2014/01/29 13:50//
=====Definiendo una clave primaria compuesta=====
Cuando nuestras tablas contienen una clave primara formada por varias columnas, necesitamos realizar un mapeo especial en nuestros bean de entidad para que sea reconocida por el motor de persistencia. Para ello necesitamos crear una nueva clase que contenga todos los campos que componen dicha clave primaria.
Esta clase solo puede contener tipos primitivos de Java, sustituye al valor de la propiedad marcada con **@Id** y aparecerá anotada en nuestro bean con la anotación **@EmbeddedId**.
Junto a está anotación, utilizaremos @**AttributeOverrides** que permite indicar un conjunto de propiedades que se van a contener en la clase que contiene la clave primaria. Dentro de @AttributeOverrides, utilizaremos la anotación **@AttributeOverride** para identificar las propiedades que se contendran en dicha clase. @AttributeOverride tiene varias propiedades:
* **name**: Indica el nombre de la propiedad en la nueva clase.
* **column**: Ppermite utilizar la anotación @Column para especificar las propiedades de la columna, tiene que coincidir con el contenido de la anotación @Column en la nueva clase.
Es imprescindible que tanto en la clase que representa la clave, como en la clase que representa la entidad, se implementen los métodos **equals** y **hashCode** para asegurar que las búsquedas Java devuelven correctamente los objetos que buscamos y se hagan correctamente las comparaciones.
@Entity
public class Entidad {
private EntidadId id;
...
public Entidad() { }
public Entidad(EntidadId id) {
this.id = id;
}
// Getters y Setters
@EmbeddedId
@AttributeOverrides({
@AttributeOverride(name="id", column=@Column(name="ID")),
@AttributeOverride(name="nombre", column=@Column(name="NOMBRE"))
})
public EntidadId getId() {
return this.id;
}
public void setId(EntidadId id) {
this.id = id;
}
public boolean equals(Object o) {
....
....
}
public int hashCode() {
....
....
}
}
@Embeddable
public class EntidadId {
int id;
String nombre;
public EntidadId() { }
public EntidadId(int id, String nombre) {
this.id = id;
this.nonmbre = nombre;
}
public boolean equals(Object o) {
....
....
}
public int hashCode() {
....
....
}
}
=====Caso especial: Clave primaria con tipo de dato no primitivo=====
Hay casos en los que existen relaciones entre entidades donde la clave primaria compuesta de una de las entidades incluye una referencia al objeto de la otra. Como en las claves primarias compuestas sólo pueden aparecer tipos primitivos tendremos que tratar este caso de forma particular.
Veámoslo con un ejemplo:
Imaginemos que tenemos una entidad grupo relacionada con N proyectos, y que la clave primaria del proyecto incluye el identificador del grupo.
**La entidad grupo**
@Entity
@Table(name = "GRUPOS_CL")
public class GruposCl implements java.io.Serializable {
private String codGrupo;
private String desGrupo;
private Set proyectosCls = new HashSet(0);
...
@Id
@Column(name = "COD_GRUPO", unique = true, nullable = false, length = 3)
@NotNull
@Length(max = 3)
public String getCodGrupo() {
return this.codGrupo;
}
**La clase de la clave primaria compuesta**
En esta clase incluimos los identificadores del proyecto y del grupo, no las referencias a los objetos de la clase.
@Embeddable
public class ProyectosClId implements java.io.Serializable {
private String codGrupo;
private String codProyecto;
...
**La entidad Proyectos**
Contiene la referencia a la clase que es la clave primaria y además contiene una referencia a la clase GruposCl, especificacndo el tipo de relación que hay entre las entidades.
@Entity
@Table(name = "PROYECTOS_CL")
public class ProyectosCl implements java.io.Serializable {
private ProyectosClId id;
private GruposCl gruposCl;
private String desProyecto;
...
@EmbeddedId
@AttributeOverrides({
@AttributeOverride(name = "codGrupo", column = @Column(name = "COD_GRUPO", nullable = false, length = 3)),
@AttributeOverride(name = "codProyecto", column = @Column(name = "COD_PROYECTO", nullable = false, length = 3))})
@NotNull
public ProyectosClId getId() {
return this.id;
}
...
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "COD_GRUPO", nullable = false, insertable = false, updatable = false)
@NotNull
public GruposCl getGruposCl() {
return this.gruposCl;
}
public void setGruposCl(GruposCl gruposCl) {
this.gruposCl = gruposCl;
}