有人可以向我解释任何相关的注释(@Any
,@AnyMetaDef
,@AnyMetaDefs
和@ManyToAny
)如何在实践中发挥作用。我很难找到任何有用的文档(仅JavaDoc并不是很有帮助)。
到目前为止,我已经收集到它们以某种方式启用了对抽象和扩展类的引用。如果是这种情况,为什么没有@OneToAny
注释?这个“任何”指的是单个“任何”或多个“任何”吗?
非常感谢一个简短,实用且具有说明性的例子(无需编译)。
编辑:尽可能多地接受回复作为答案并给予应有的信用,我发现Smink和Sakana的答案都提供了丰富的信息。因为我不能接受几个回复答案,所以我很遗憾地将其标记为答案。
答案 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
}