首页 文章

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

提问于
浏览
1

我已经使用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 回答

  • 4

    辅助表通常用于将单个实体的内容映射到两个表 . 它不允许使用标准JPA注释进行延迟/选择提取 . 您可以使用专有的Hibernate注释来使用单独的选择加载它,但仅在必要时使用 . 见http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#mapping-declaration-join

    fetch:如果设置为JOIN,默认情况下,Hibernate将使用内部联接来检索由类或其超类定义的辅助表以及由子类定义的辅助表的外部联接 . 如果设置为SELECT,则Hibernate将对子类上定义的辅助表使用顺序选择,仅当行结果表示子类的实例时才会发出 . 内部联接仍将用于检索由类及其超类定义的辅助 .

    因此,将Hibernate @Table 注释的 fetch 属性设置为 SELECT 将执行您想要的操作:将发出附加的select子句以从相应的辅助表中选择值 .

    如果你想要延迟抓取,那么辅助表就不是你想要的了 . 你必须使用关联来做到这一点 .

相关问题