我已经使用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 . 这使得在查询执行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关系时,如何实现我只需要加载Parent类中的字段的要求?
谢谢 .
1 回答
辅助表通常用于将单个实体的内容映射到两个表 . 它不允许使用标准JPA注释进行延迟/选择提取 . 您可以使用专有的Hibernate注释来使用单独的选择加载它,但仅在必要时使用 . 见http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#mapping-declaration-join:
因此,将Hibernate
@Table
注释的fetch
属性设置为SELECT
将执行您想要的操作:将发出附加的select子句以从相应的辅助表中选择值 .如果你想要延迟抓取,那么辅助表就不是你想要的了 . 你必须使用关联来做到这一点 .