¿Cómo usar Hibernate @ Any-related annotations?

¿Podría alguien explicarme cómo funcionan las anotaciones relacionadas con Any ( @Any , @AnyMetaDef , @AnyMetaDefs y @ManyToAny ) en la práctica? Tengo dificultades para encontrar cualquier documentación útil (JavaDoc solo no es muy útil) acerca de estos.

Hasta ahora he llegado a la conclusión de que de alguna manera permiten la referencia a clases abstractas y extendidas. Si este es el caso, ¿por qué no hay una anotación @OneToAny ? ¿Y este ‘cualquiera’ se está refiriendo a un único ‘cualquiera’, o múltiple ‘cualquiera’?

Un ejemplo corto, práctico e ilustrativo sería muy apreciado (no tiene que comstackrse).

Editar: por más que me gustaría aceptar respuestas como respuestas y dar crédito donde merezca, las respuestas de Smink y Sakana me resultaron informativas. Como no puedo aceptar varias respuestas como la respuesta , desafortunadamente no marcaré como la respuesta.

Espero que este artículo arroje algo de luz sobre el tema:

A veces necesitamos asignar una propiedad de asociación a diferentes tipos de entidades que no tienen una entidad antecesora común, por lo que una asociación polimórfica simple no hace el trabajo.

Por ejemplo, supongamos tres aplicaciones diferentes que administran una biblioteca de medios: la primera aplicación administra préstamos de libros, la segunda DVD y la tercera VHS. Las aplicaciones no tienen nada en común. Ahora queremos desarrollar una nueva aplicación que administre los tres tipos de medios y reutilice las entidades existentes de libros, DVD y VHS. Dado que las clases de libro, DVD y VHS provienen de diferentes aplicaciones, no tienen ninguna entidad antecesora; el antecesor común es java.lang.Object. Sin embargo, nos gustaría tener una entidad de préstamo que pueda referirse a cualquiera de los tipos de medios posibles.

Para resolver este tipo de referencias podemos usar cualquier mapeo. esta asignación siempre incluye más de una columna: una columna incluye el tipo de entidad a la que se refiere la propiedad mapeada actual y la otra incluye la identidad de la entidad; por ejemplo, si nos referimos a un libro, la primera columna incluirá un marcador para el tipo de entidad Libro y el segundo incluirá la identificación del libro específico.

 @Entity @Table(name = "BORROW") public class Borrow{ @Id @GeneratedValue private Long id; @Any(metaColumn = @Column(name = "ITEM_TYPE")) @AnyMetaDef(idType = "long", metaType = "string", metaValues = { @MetaValue(targetEntity = Book.class, value = "B"), @MetaValue(targetEntity = VHS.class, value = "V"), @MetaValue(targetEntity = DVD.class, value = "D") }) @JoinColumn(name="ITEM_ID") private Object item; ....... public Object getItem() { return item; } public void setItem(Object item) { this.item = item; } } 

La anotación @Any define una asociación polimórfica a las clases de varias tablas. Este tipo de mapeo siempre requiere más de una columna. La primera columna contiene el tipo de entidad asociada. Las columnas restantes tienen el identificador. Es imposible especificar una restricción de clave externa para este tipo de asociación, por lo que no se entiende como la forma habitual de asociación de mapeo (polimórficos). Debe usar esto solo en casos muy especiales (por ejemplo, registros de auditoría, datos de sesión de usuario, etc.). La anotación @Any describe la columna que contiene la información de metadatos. Para vincular el valor de la información de metadatos y un tipo de entidad real, se utilizan las anotaciones @AnyDef y @AnyDefs.

 @Any( metaColumn = @Column( name = "property_type" ), fetch=FetchType.EAGER ) @AnyMetaDef( idType = "integer", metaType = "string", metaValues = { @MetaValue( value = "S", targetEntity = StringProperty.class ), @MetaValue( value = "I", targetEntity = IntegerProperty.class ) } ) @JoinColumn( name = "property_id" ) public Property getMainProperty() { return mainProperty; } 

idType representa el tipo de propiedad del identificador de entidades de destino y metaType el tipo de metadata (generalmente String). Tenga en cuenta que @AnyDef se puede mutualizar y reutilizar. Se recomienda colocarlo como un metadato de paquete en este caso.

 //on a package @AnyMetaDef( name="property" idType = "integer", metaType = "string", metaValues = { @MetaValue( value = "S", targetEntity = StringProperty.class ), @MetaValue( value = "I", targetEntity = IntegerProperty.class ) } ) package org.hibernate.test.annotations.any; //in a class @Any( metaDef="property", metaColumn = @Column( name = "property_type" ), fetch=FetchType.EAGER ) @JoinColumn( name = "property_id" ) public Property getMainProperty() { return mainProperty; } 

@ManyToAny permite asociaciones polimórficas a clases de múltiples tablas. Este tipo de mapeo siempre requiere más de una columna. La primera columna contiene el tipo de entidad asociada. Las columnas restantes tienen el identificador. Es imposible especificar una restricción de clave externa para este tipo de asociación, por lo que no se entiende como la forma habitual de asociación de mapeo (polimórficos). Debe usar esto solo en casos muy especiales (por ejemplo, registros de auditoría, datos de sesión de usuario, etc.).

 @ManyToAny( metaColumn = @Column( name = "property_type" ) ) @AnyMetaDef( idType = "integer", metaType = "string", metaValues = { @MetaValue( value = "S", targetEntity = StringProperty.class ), @MetaValue( value = "I", targetEntity = IntegerProperty.class ) } ) @Cascade( { org.hibernate.annotations.CascadeType.ALL } ) @JoinTable( name = "obj_properties", joinColumns = @JoinColumn( name = "obj_id" ), inverseJoinColumns = @JoinColumn( name = "property_id" ) ) public List getGeneralProperties() { 

Src: Guía de referencia de anotaciones de Hibernate 3.4.0GA

¡Espero eso ayude!

¿Has leído la documentación de Anotaciones de Hibernate para @Any ? Todavía no lo he usado, pero parece una forma extendida de definir referencias. El enlace incluye un ejemplo, aunque no sé si es suficiente para comprender completamente el concepto …

La anotación @Any define una asociación polimórfica a las clases de varias tablas, a la derecha, pero las asociaciones polimórficas como estas son un anti-patrón de SQL. La razón principal es que no puede definir una restricción FK si una columna puede referirse a más de una tabla.

Una de las soluciones, señalada por Bill Karwin en su libro, es crear tablas de intersección para cada tipo de “Cualquiera”, en lugar de usar una sola columna con “tipo”, y usar el modificador exclusivo para evitar duplicados. Esta solución puede ser un dolor para trabajar con JPA.

Otra solución, también propuesta por Karwin, es crear un super-tipo para los elementos conectados. Tomando el ejemplo de tomar prestado un libro, DVD o VHS, puede crear un elemento de tipo súper, y hacer que Book, DVD y VHS hereden de Item, con la estrategia de tabla unida. Pedir prestado luego apunta al artículo. De esta forma evitas por completo el problema de FK. Traducí el ejemplo del libro a JPA abajo:

 @Entity @Table(name = "BORROW") public class Borrow{ //... id, ... @ManyToOne Item item; //... } @Entity @Table(name = "ITEMS") @Inheritance(strategy=JOINED) public class Item{ // id, .... // you can add a reverse OneToMany here to borrow. } @Entity @Table(name = "BOOKS") public class Book extends Item { // book attributes } @Entity @Table(name = "VHS") public class VHS extends Item { // VHSattributes } @Entity @Table(name = "DVD") public class DVD extends Item { // DVD attributes }