如何使用Hibernate @ Any-related注释?

有人可以向我解释任何相关的注释( @AnyMetaDef@AnyMetaDefs @AnyMetaDef@AnyMetaDefs@ManyToAny )如何在实践中发挥作用。 我很难找到任何有用的文档(仅JavaDoc并不是很有帮助)。

到目前为止,我已经收集到它们以某种方式启用对抽象和扩展类的引用。 如果是这种情况,为什么没有@OneToAny注释? 这个“任何”指的是单个“任何”或多个“任何”吗?

一个简短,实用和说明的例子将非常受欢迎(不必编译)。

编辑:尽管我希望接受回复作为答案并给予应有的信用,但我发现Smink和Sakana的答案都提供了丰富的信息。 因为我不能接受几个回复作为答案 ,遗憾的是我不会将其作为答案。

希望这篇文章能够为这个主题带来一些启示:

有时我们需要将关联属性映射到不具有共同祖先实体的不同类型的实体 – 因此简单的多态关联不起作用。

例如,我们假设有三个不同的应用程序来管理媒体库 – 第一个应用程序管理书籍借阅,第二个应用程序管理DVD,第三个VHS。 应用程序没有任何共同之处。 现在我们要开发一个新的应用程序来管理所有三种媒体类型,并重用现有的Book,DVD和VHS实体。 由于Book,DVD和VHS类来自不同的应用程序,因此它们没有任何祖先实体 – 共同的祖先是java.lang.Object。 我们仍然希望有一个Borrow实体可以引用任何可能的媒体类型。

要解决这种类型的引用,我们可以使用任何映射。 此映射始终包含多个列:一列包含当前映射属性引用的实体的类型,另一列包括实体的标识,例如,如果我们引用一本书,则第一列将包含标记Book实体类型和第二个实体类型将包含特定书籍的ID。

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

@Any注释定义了与多个表中的类的多态关联。 这种类型的映射始终需要多个列。 第一列包含关联实体的类型。 其余列包含标识符。 为这种关联指定外键约束是不可能的,因此这绝对不是映射(多态)关联的常用方法。 您应该仅在非常特殊的情况下使用它(例如,审计日志,用户会话数据等)。 @Any注释描述了包含元数据信息的列。 要链接元数据信息的值和实际实体类型,请使用@AnyDef和@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表示目标实体标识符属性类型,metaType表示元数据类型(通常为String)。 请注意,@ AnyDef可以共享和重用。 在这种情况下,建议将其作为包元数据放置。

 //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允许多个表与多个表的多态关联。 这种类型的映射始终需要多个列。 第一列包含关联实体的类型。 其余列包含标识符。 为这种关联指定外键约束是不可能的,因此这绝对不是映射(多态)关联的常用方法。 您应该仅在非常特殊的情况下使用它(例如,审计日志,用户会话数据等)。

 @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: Hibernate Annotations参考指南3.4.0GA

希望能帮助到你!

您是否阅读过@Any的Hibernate Annotations文档 ? 我自己还没有使用过那个,但它看起来像是一些定义引用的扩展方式。 该链接包含一个例子,但我不知道它是否足以完全理解这个概念……

@Any注释定义了来自多个表的类的多态关联,对,但这些多态关联是SQL反模式! 主要原因是如果列可以引用多个表,则无法定义FK约束。

Bill Karwin在他的书中指出的解决方案之一是为每种类型的“Any”创建交集表,而不是使用一个具有“type”的列,并使用unique修饰符来避免重复。 这个解决方案可能是与JPA一起工作的痛苦。

Karwin提出的另一种解决方案是为连接元素创建超类型。 借用Book,DVD或VHS的例子,您可以创建一个超类型的项目,并使用连接表的策略使Book,DVD和VHSinheritance自Item。 然后借用指向物品。 这样你就完全避免了FK问题。 我将这本书的例子翻译成JPA轰鸣声:

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