java does - Qué anotación debería usar: @IdClass o @EmbeddedId





primary multiple (7)


Con EmbeddedId puede usar la cláusula IN en HQL, por ejemplo: FROM Entity WHERE id IN :ids donde id es un EmbeddedId, mientras que es doloroso lograr el mismo resultado con IdClass, querrá hacer algo como FROM Entity WHERE idPartA = :idPartA0 AND idPartB = :idPartB0 .... OR idPartA = :idPartAN AND idPartB = :idPartBN

La especificación JPA (Java Persistence API) tiene 2 formas diferentes de especificar claves compuestas de entidad: @IdClass y @EmbeddedId .

Estoy utilizando ambas anotaciones en las entidades asignadas, pero resulta ser un gran desastre para las personas que no están muy familiarizadas con JPA .

Quiero adoptar solo una forma de especificar claves compuestas. ¿Cuál es realmente el mejor? ¿Por qué?




La clave compuesta no debe tener una propiedad @EmbeddedId cuando se usa @EmbeddedId .




Considero que @EmbeddedId es probablemente más detallado porque con @IdClass no se puede acceder a todo el objeto de la clave principal usando cualquier operador de acceso de campo. Usando @EmbeddedId puedes hacer esto:

@Embeddable class EmployeeId { name, dataOfBirth }
@Entity class Employee {
  @EmbeddedId EmployeeId employeeId;
  ...
}

Esto proporciona una noción clara de los campos que componen la clave compuesta porque todos se agregan en una clase a la que se accede a través de un operador de acceso de campo.

Otra diferencia con @IdClass y @EmbeddedId es cuando se trata de escribir HQL:

Con @IdClass escribes:

select e.name from Employee e

y con @EmbeddedId tienes que escribir:

select e.employeeId.name from Employee e

Tienes que escribir más texto para la misma consulta. Algunos pueden argumentar que esto difiere de un lenguaje más natural como el promovido por IdClass . Pero la mayoría de las veces entender desde la consulta que un campo dado es parte de la clave compuesta es de una ayuda invaluable.




Creo que la principal ventaja es que podríamos usar @GeneratedValue para el id cuando usamos @IdClass ? Estoy seguro de que no podemos usar @GeneratedValue para @EmbeddedId .




Por lo que sé, si su PK compuesta contiene FK, es más fácil y más sencillo usar @IdClass

Con @EmbeddedId tiene que definir la asignación para su columna FK dos veces, onece en @Embeddedable y una vez para, por ejemplo, @ManyToOne donde @ManyToOne tiene que ser de solo lectura ( @PrimaryKeyJoinColumn ) porque no puede tener una columna establecida en dos variables (posibles conflictos).
Entonces debes establecer tu FK usando el tipo simple en @Embeddedable .

En el otro sitio usando @IdClass esta situación se puede manejar mucho más fácilmente como se muestra en las claves primarias a través de las relaciones OneToOne y ManyToOne :

Ejemplo de anotación de identificación de JPA 2.0 ManyToOne

...
@Entity
@IdClass(PhonePK.class)
public class Phone {

    @Id
    private String type;

    @ManyToOne
    @Id
    @JoinColumn(name="OWNER_ID", referencedColumnName="EMP_ID")
    private Employee owner;
    ...
}

Ejemplo de clase de identificación JPA 2.0

...
public class PhonePK {
    private String type;
    private long owner;

    public PhonePK() {}

    public PhonePK(String type, long owner) {
        this.type = type;
        this.owner = owner;
    }

    public boolean equals(Object object) {
        if (object instanceof PhonePK) {
            PhonePK pk = (PhonePK)object;
            return type.equals(pk.type) && owner == pk.owner;
        } else {
            return false;
        }
    }

    public int hashCode() {
        return type.hashCode() + owner;
    }
}



Hay tres estrategias para usar una clave primaria compuesta:

  • Marque como @Embeddable y agregue a su clase de entidad una propiedad normal para él, marcada con @Id .
  • Agregue a su clase de entidad una propiedad normal para él, marcada con @EmbeddedId .
  • Agregue propiedades a su clase de entidad para todos sus campos, @Id con @Id y marque su clase de entidad con @IdClass , suministrando la clase de su clase de clave primaria.

El uso de @Id con una clase marcada como @Embeddable es el enfoque más natural. La etiqueta @Embeddable se puede usar de todos modos para valores no @Embeddable clave primaria. Le permite tratar la clave primaria compuesta como una sola propiedad, y permite la reutilización de la clase @Embeddable en otras tablas.

El siguiente enfoque más natural es el uso de la etiqueta @EmbeddedId . Aquí, la clase de clave primaria no se puede usar en otras tablas, ya que no es una entidad @Embeddable , pero nos permite tratar la clave como un atributo único de alguna clase.

Finalmente, el uso de las anotaciones @IdClass y @Id nos permite mapear la clase de clave primaria compuesta usando las propiedades de la entidad correspondiente a los nombres de las propiedades en la clase de clave primaria. Los nombres deben corresponderse (no existe un mecanismo para anular esto), y la clase de clave primaria debe cumplir las mismas obligaciones que con las otras dos técnicas. La única ventaja de este enfoque es su capacidad para "ocultar" el uso de la clase de clave primaria desde la interfaz de la entidad que lo contiene. La anotación @IdClass toma un parámetro de valor del tipo Clase, que debe ser la clase que se utilizará como la clave primaria compuesta. Los campos que corresponden a las propiedades de la clase de clave primaria que se utilizarán se deben anotar con @Id .

Referencia: http://www.apress.com/us/book/9781430228509




En cuanto a un ejemplo en el que el serialVersionUID faltante podría causar un problema:

Estoy trabajando en esta aplicación Java EE que se compone de un módulo web que utiliza un módulo EJB . El módulo web llama al módulo EJB forma remota y pasa un POJO que implementa Serializable como un argumento.

Esta clase POJO's se empaquetó dentro del jar de EJB y dentro de su propio jar en el WEB-INF / lib del módulo web. En realidad, son la misma clase, pero cuando empaco el módulo EJB desempaqueto el frasco de este POJO para empaquetarlo junto con el módulo EJB.

La llamada al EJB estaba fallando con la excepción a continuación porque no había declarado su serialVersionUID :

Caused by: java.io.IOException: Mismatched serialization UIDs : Source
 (Rep.
 IDRMI:com.hordine.pedra.softbudget.domain.Budget:5CF7CE11E6810A36:04A3FEBED5DA4588)
 = 04A3FEBED5DA4588 whereas Target (Rep. ID RMI:com.hordine.pedra.softbudget.domain.Budget:7AF5ED7A7CFDFF31:6227F23FA74A9A52)
 = 6227F23FA74A9A52




java jpa annotations java-persistence-api