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

发布于 2024-12-11 12:34:36 字数 1879 浏览 0 评论 0原文

我已经使用 InheritanceType.Single_Table 和鉴别器列在 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;
} 

我现在有一个与父类具有 @OneToOne 关系的实体。该实体只需要使用父类中的值字段。它永远不需要使用 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 类中的字段的要求?

谢谢。

I have mapped my inheritance hierarchy in Hibernate using InheritanceType.Single_Table and discriminator columns to distinguish between the different entities. All subclasses of the superclass store their fields into secondary tables. As an example:

@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;
} 

I now have an Entity that has a @OneToOne relationship with the Parent class. This Entity only needs to work with the value field from the Parent class. It will never need to work with any fields from any subclass of Parent

@Entity
public class AnotherEntity extends Base
{
    @JoinColumn(name="parentId")
    @OneToOne(fetch=FetchType.Lazy, optional=true, targetEntity=Parent.class)
    private Parent parent;
 }

What I want to happen is that only the fields of Parent.class are selected when the relationship to parent is loaded from the database. What I'm seeing is that Hibernate attempts to load all properties of the entities that extend Parent. It also left joins all of the Secondary tables. This is problematic as I have rougly 30 entities that extend Parent. This makes fetching the Parent entity non-viable as the query performs 30 joins.

As an example, this is the type of query I am seeing:

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 

I don't understand why Hibernate decides to select a superset of all properties defined in the subclasses of Parent and join all of the secondary tables? I could understand it joining the secondary table for entity defined by the discriminator value of the parent being referenced, but otherwise I am confused.

My question is, how do I go about achieving my requirement of only having the fields from the Parent class loaded when I retrieve the Parent relationship in the AnotherEntity class?

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

从来不烧饼 2024-12-18 12:34:36

辅助表通常用于将单个实体的内容映射到两个表。它不允许使用标准 JPA 注释进行惰性/选择获取。您可以使用专有的 Hibernate 注释通过单独的选择来加载它,而且仅在必要时才这样做。请参阅http://docs.jboss .org/hibernate/core/3.6/reference/en-US/html_single/#mapping-declaration-join

fetch:如果设置为JOIN,默认情况下,Hibernate将使用内连接
检索由类或其超类定义的辅助表
以及由子类定义的辅助表的外连接。如果设置
到 SELECT 然后 Hibernate 将使用顺序选择作为辅助
在子类上定义的表,仅当行翻转时才会发出
out 代表子类的一个实例。内连接仍然会
用于检索由类及其定义的辅助对象
超类。

因此,将 Hibernate @Table 注释的 fetch 属性设置为 SELECT 将执行您想要的操作:将发出一个附加的 select 子句来选择仅来自适当的辅助表的值。

如果您想要延迟获取,那么辅助表不是您想要的。您必须使用关联来完成此操作。

A secondary table is normally used to map the content of a single entity to two tables. It doesn't allow for lazy/select fetching using standard JPA annotations. You may use a proprietary Hibernate annotation to load it using a separate select, and only if necessary, though. See http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#mapping-declaration-join:

fetch: If set to JOIN, the default, Hibernate will use an inner join
to retrieve a secondary table defined by a class or its superclasses
and an outer join for a secondary table defined by a subclass. If set
to SELECT then Hibernate will use a sequential select for a secondary
table defined on a subclass, which will be issued only if a row turns
out to represent an instance of the subclass. Inner joins will still
be used to retrieve a secondary defined by the class and its
superclasses.

So setting the fetch attribute of the Hibernate @Table annotation to SELECT will do what you want : an additional select clause will be issued to select the values from just the appropriate secondary table.

If you want lazy fetching, then a secondary table is not what you want. You'll have to do it using associations.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文