我使用InheritanceType.Single_Table和discriminator列在Hibernate中映射了我的继承层次结构,以区分不同的实体。超类的所有子类都将其字段存储到辅助表中。举个例子:
@MappedSuperclass
public abstract class Base
{
@Id
private String id;
@Version
private long version;
}
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "type", discriminatorType = DiscriminatorType.STRING)
public class Parent extends Base
{
@Column(nullable=false)
private BigDecimal value;
}
@Entity
@DiscriminatorValue("child1")
@SecondaryTable(name = "Child1")
public class Child1 extends Parent
{
@Column(table="Child1")
private String name;
}
@Entity
@DiscriminatorValue("child2")
@SecondaryTable(name = "Child2")
public class Child2 extends Parent
{
@Column(table="Child2")
private String name2;
}
我现在有一个与Parent类有@OneToOne关系的Entity。此实体只需要使用Parent类中的value字段。它永远不需要使用Parent
的任何子类中的任何字段@Entity
public class AnotherEntity extends Base
{
@JoinColumn(name="parentId")
@OneToOne(fetch=FetchType.Lazy, optional=true, targetEntity=Parent.class)
private Parent parent;
}
我想要发生的是,当从数据库加载与父级的关系时,只选择Parent.class的字段。我所看到的是Hibernate试图加载扩展Parent的实体的所有属性。它还会加入所有辅助表。这是有问题的,因为我有粗略的30个实体扩展Parent。这使得获取Parent实体不可行,因为查询执行30个连接。
例如,这是我看到的查询类型:
Hibernate:
select
parent.id as id3_0_,
parent_.version as version3_0_,
parent.name1 as name110_3_0_,
parent.name2 as name24_3_0_,
parent.type as type3_0_
from
Parent parent0_
left outer join
Child1 parent0_2_
on parent0_.id=parent0_2_.id
left outer join
Child2 parent0_3_
on parent0_.id=parent0_3_.id
我不明白为什么Hibernate决定选择Parent子类中定义的所有属性的超集并加入所有辅助表?我可以理解它加入了被引用的父类的鉴别器值定义的实体的辅助表,但是我很困惑。
我的问题是,当我在AnotherEntity类中检索父关系时,如何实现我只需要加载Parent类中的字段的要求?
感谢。
答案 0 :(得分:4)
辅助表通常用于将单个实体的内容映射到两个表。它不允许使用标准JPA注释进行延迟/选择提取。您可以使用专有的Hibernate注释来使用单独的选择加载它,但仅在必要时使用。见http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#mapping-declaration-join:
fetch:如果设置为JOIN,默认情况下,Hibernate将使用内连接 检索由类或其超类定义的辅助表 和子类定义的辅助表的外连接。如果设置 然后,Hibernate将使用顺序选择辅助 在子类上定义的表,仅在行转动时才会发出 out表示子类的实例。内部联接仍然会 用于检索由类及其定义的辅助 超类。
因此,将Hibernate fetch
注释的@Table
属性设置为SELECT
将执行您想要的操作:将发出另一个select子句以从相应的辅助表中选择值
如果你想要延迟抓取,那么辅助表就不是你想要的了。你必须使用协会来做。