带有超类的Hibernate @OneToOne,仅在连接时检索超类字段

时间:2011-10-25 10:57:57

标签: java hibernate inheritance jpa one-to-one

我使用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类中的字段的要求?

感谢。

1 个答案:

答案 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子句以从相应的辅助表中选择值

如果你想要延迟抓取,那么辅助表就不是你想要的了。你必须使用协会来做。