Hibernate @OneToOne 带有超类,仅在连接时检索超类字段
我已经使用 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
辅助表通常用于将单个实体的内容映射到两个表。它不允许使用标准 JPA 注释进行惰性/选择获取。您可以使用专有的 Hibernate 注释通过单独的选择来加载它,而且仅在必要时才这样做。请参阅http://docs.jboss .org/hibernate/core/3.6/reference/en-US/html_single/#mapping-declaration-join:
因此,将 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:
So setting the
fetch
attribute of the Hibernate@Table
annotation toSELECT
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.