我正在使用Hibernate连接到我的数据库。 我的应用程序中有一个继承结构。问题是,当我执行像“from Animal”这样的查询时,它为Animal类,它的子类以及Animal及其子类的所有关联做了一个左外连接。 我如何避免这种情况。我想只在我通过条件查询中的fetchmode指定数据时才加载数据?
答案 0 :(得分:17)
是的,Hibernate支持多态查询。来自文档:
14.8. Polymorphic queries
如下的查询:
from Cat as cat
不仅会返回
Cat
的实例,还会返回 也像DomesticCat
这样的子类。 Hibernate查询可以命名任何 Java from子句中的类或接口。 查询将返回所有实例 扩展它的持久化类 类或实现接口。该 以下查询将返回全部 持久对象:from java.lang.Object o
界面
Named
可能是 由各种持久性实施 类:from Named n, Named m where n.name = m.name
最后两个查询将需要 多个SQL
SELECT
。这意味着 order by子句没有 正确排序整个结果集。 这也意味着你不能打电话给这些 使用Query.scroll()
进行查询。
这是默认行为(称为隐式多态),Hibernate同时支持隐式和显式多态:
隐式多态意味着该类的实例将是 由任何命名的查询返回 超类或实现的接口或 类,以及任何实例 将返回该类的子类 通过命名该类的查询 本身。 显式多态性意味着 将返回该类实例 仅通过明确命名的查询 那个班。命名的查询 class只返回实例 子类映射在此内部
<class>
声明为<subclass>
或<joined-subclass>
。 对于大多数目的,默认polymorphism="implicit"
是 适当。显式多态性是 当两个不同的类是有用的 映射到同一个表这允许a “轻量级”类包含一个 表格列的子集。
这可以在班级配置。如果您正在使用xml映射,请使用polymorphism="explicit"
,请参阅5.1.3 Class。如果您正在使用注释,请使用Hibernate的@Entity
注释,请参阅2.4.1. Entity。下面是一个例子:
@javax.persistence.Entity
@org.hibernate.annotations.Entity(polymorphism = PolymorphismType.EXPLICIT)
@Inheritance(strategy = InheritanceType.JOINED)
public class Foo {
...
}
答案 1 :(得分:3)
假设你有一个类结构如下:
class Animal { }
class Dog : Animal { }
class Cat : Animal { }
然后当您选择所有Animal
时,您还希望加载所有Dog
和Cat
s。毕竟它们是Animal
s。
不同的故事是协会。您可以创建映射,使得关联是延迟加载而不是急切加载。
答案 2 :(得分:0)
基本上它是Hibernate使用的默认ORM继承设计模式,称为类继承(所有类都映射到单个表),如果你想改变你可以google:
- 每个类的单类hierarhy或表(这会将每个类映射到DB中的单独表)
- 具体类hierarhy(这将只将具体实现映射到表)。
答案 3 :(得分:0)
要避免在类层次结构提取期间出现多个连接,可以应用SINGLE_TABLE层次结构映射策略,然后使用SELECT提取策略在子类上定义辅助表。但是,这会将“重型连接”模型转换为“N + 1选择”模型。例子:
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = Super.DISCRIMINATOR_COLUMN, discriminatorType = DiscriminatorType .STRING, length = 255)
public class Super {
public static final String DISCRIMINATOR_COLUMN = "classname";
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
protected long id;
@Column(updatable = false, insertable = false)
protected String classname;
protected String superProp = "superProp";
public long getId() {
return id;
}
public String getClassname() {
return classname;
}
public String getSuperProp() {
return superProp;
}
public void setSuperProp(String superProp) {
this.superProp = superProp;
}
}
@Entity
@SecondaryTable(name = SubA.TABLE)
@Table(appliesTo = SubA.TABLE, fetch = FetchMode.SELECT)
public class SubA extends Super {
public static final String TABLE = "SUBA";
@Column(table = TABLE)
protected String subAProp = "subAProp";
public String getSubAProp() {
return subAProp;
}
public void setSubAProp(String subAProp) {
this.subAProp = subAProp;
}
}
@Entity
@SecondaryTable(name = SubB.TABLE)
@Table(appliesTo = SubB.TABLE, fetch = FetchMode.SELECT)
public class SubB extends Super {
public static final String TABLE = "SUBB";
@Column(table = TABLE)
protected String subBProp = "subBProp";
public String getSubBProp() {
return subBProp;
}
public void setSubBProp(String subBProp) {
this.subBProp = subBProp;
}
}
在from Super
HQL查询上执行了什么SQL:
select [...] from SUPER super0_
select super_1_.subaprop as subaprop1_83_ from SUBA super_1_ where super_1_.id=1
select super_2_.subbprop as subbprop1_84_ from SUBB super_2_ where super_2_.id=2
有关此方法和一般hibernate性能提示的更多信息,请参阅my article。