Como usar o Hibernate @ Anotações relacionadas?

Alguém poderia me explicar como quaisquer annotations relacionadas ( @Any , @AnyMetaDef , @AnyMetaDefs e @ManyToAny ) funcionam na prática. Eu tenho dificuldade em encontrar qualquer documentação útil (JavaDoc sozinho não é muito útil) sobre estes.

Até agora, concluí que eles de alguma forma permitem a referência a classs abstratas e estendidas. Se este for o caso, por que não há uma anotação @OneToAny ? E isso é “qualquer” referindo-se a um único “qualquer” ou múltiplo “qualquer”?

Um exemplo curto, prático e ilustrativo seria muito apreciado (não precisa ser compilado).

Edit: por mais que eu gostaria de aceitar respostas como respostas e dar crédito onde vencido, eu achei as respostas de Smink e Sakana informativas. Como não posso aceitar várias respostas como resposta , infelizmente não vou marcar nem como resposta.

Espero que este artigo traga alguma luz para o assunto:

Às vezes, precisamos mapear uma propriedade de associação para tipos diferentes de entidades que não possuem uma entidade ancestral comum – portanto, uma associação polimórfica simples não funciona.

Por exemplo, vamos supor três aplicativos diferentes que gerenciam uma biblioteca de mídia – o primeiro aplicativo gerencia os empréstimos de livros, o segundo os DVDs e os terceiros VHSs. As aplicações não têm nada em comum. Agora, queremos desenvolver um novo aplicativo que gerencie todos os três tipos de mídia e reutilize as entidades Book, DVD e VHS existentes. Como as classs Book, DVD e VHS vêm de aplicativos diferentes, elas não têm nenhuma entidade ancestral – o ancestral comum é java.lang.Object. Ainda assim, gostaríamos de ter uma entidade de Empréstimo que possa se referir a qualquer tipo de mídia possível.

Para resolver este tipo de referências, podemos usar qualquer mapeamento. esse mapeamento sempre inclui mais de uma coluna: uma coluna inclui o tipo de entidade a que a propriedade mapeada atual se refere e a outra inclui a identidade da entidade, por exemplo, se nos referirmos a um livro, a primeira coluna includeá um marcador para o tipo de entidade Book e o segundo includeá o id do livro 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; } } 

A anotação @Any define uma associação polimórfica para classs de várias tabelas. Esse tipo de mapeamento sempre requer mais de uma coluna. A primeira coluna contém o tipo da entidade associada. As colunas restantes contêm o identificador. É impossível especificar uma restrição de chave estrangeira para esse tipo de associação, portanto, isso não é certamente a maneira usual de mapear associações (polimórficas). Você deve usar isso apenas em casos muito especiais (por exemplo, logs de auditoria, dados de session do usuário, etc.). A anotação @Any descreve a coluna que contém as informações de metadados. Para vincular o valor das informações de metadados e um tipo de entidade real, as annotations @AnyDef e @AnyDefs são usadas.

 @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 o tipo de propriedade do identificador de entidades de destino e metaType o tipo de metadados (geralmente String). Note que @AnyDef pode ser mutualizado e reutilizado. Recomenda-se colocá-lo como um metadado do pacote neste 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 associações polimórficas a classs de várias tabelas. Esse tipo de mapeamento sempre requer mais de uma coluna. A primeira coluna contém o tipo da entidade associada. As colunas restantes contêm o identificador. É impossível especificar uma restrição de chave estrangeira para esse tipo de associação, portanto, isso não é certamente a maneira usual de mapear associações (polimórficas). Você deve usar isso apenas em casos muito especiais (por exemplo, logs de auditoria, dados de session do usuário, 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: Guia de Referência de Anotações do Hibernate 3.4.0GA

Espero que ajude!

Você leu a documentação de Anotações do Hibernate para @Any ? Ainda não usei esse, mas parece um modo extenso de definir referências. O link inclui um exemplo, embora eu não saiba se é suficiente entender completamente o conceito …

A anotação @Any define uma associação polimórfica para classs de várias tabelas, mas associações polimórficas como estas são um anti-padrão SQL! A principal razão é que você não pode definir uma restrição FK se uma coluna puder se referir a mais de uma tabela.

Uma das soluções, apontada por Bill Karwin em seu livro, é criar tabelas de interseção para cada tipo de “Any”, em vez de usar uma coluna com “type” e usar o modificador exclusivo para evitar duplicatas. Esta solução pode ser uma dor para trabalhar com o JPA.

Outra solução, também proposta por Karwin, é criar um super-tipo para os elementos conectados. Tomando o exemplo do livro emprestado, DVD ou VHS, você pode criar um Item de superposição e tornar o Livro, DVD e VHS herdados do Item, com a estratégia da tabela Juntada. Emprestar então aponta para Item. Desta forma você evita completamente o problema FK. Eu traduzi o exemplo do livro para o JPA abaixo:

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