如何使用休眠@Any相关的注释?

2022-09-01 08:39:21

有人可以向我解释一下与 Any 相关的注释 (, 和 ) 在实践中是如何工作的吗?我很难找到任何有用的文档(JavaDoc本身并不是很有帮助)。@Any@AnyMetaDef@AnyMetaDefs@ManyToAny

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

一个简短,实用和说明性的示例将不胜感激(不必编译)。

编辑:尽管我想接受回复作为答案,并在适当的时候给予信任,但我发现Smink和Sakana的答案都提供了丰富的信息。因为我不能接受几个回复作为答案,所以我很遗憾地将两者都标记为答案。


答案 1

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

有时,我们需要将关联属性映射到没有共同祖先实体的不同类型的实体 - 因此普通的多态关联不会完成这项工作。

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

为了解决这种类型的引用,我们可以使用任何映射。此映射始终包含多个列:一列包括当前映射属性所引用的实体的类型,另一列包括实体的标识,例如,如果我们引用一本书,则第一列将包括书籍实体类型的标记,第二列将包括特定书籍的 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;
    }

}

答案 2

@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: 休眠注释参考指南 3.4.0GA

希望它有帮助!


推荐