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

时间:2008-10-20 09:05:30

标签: java hibernate orm annotations

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

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

非常感谢一个简短,实用且具有说明性的例子(无需编译)。

编辑:尽可能多地接受回复作为答案并给予应有的信用,我发现Smink和Sakana的答案都提供了丰富的信息。因为我不能接受几个回复答案,所以我很遗憾地将其标记为答案。

4 个答案:

答案 0 :(得分:24)

希望article为这个主题带来一些启示:

  

有时我们需要映射一个   协会财产不同   没有的实体类型   共同的祖先实体 - 所以平原   多态关联不做   工作

例如,让我们假设有三个不同的应用程序来管理媒体库 - 第一个应用程序管理书籍借阅,第二个应用程序管理书籍,第三个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;
    }

}

答案 1 :(得分:22)

@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<Property> getGeneralProperties() {

Src:Hibernate Annotations Reference Guide 3.4.0GA

希望它有帮助!

答案 2 :(得分:2)

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

答案 3 :(得分:1)

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

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

Karwin提出的另一种解决方案是为连接元素创建超类型。借用Book,DVD或VHS的例子,您可以创建一个超类型的项目,并使用连接表的策略从Book继承Book,DVD和VHS。然后借用指向物品。这样你就完全避免了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
}