java HIbernate 加载子类和类

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3412896/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 01:43:38  来源:igfitidea点击:

HIbernate loads subclasses along with classes

javahibernateorm

提问by rima

I am using Hibernate to connect to my database. I have an inheritance structure in my application.The problem is that when i do a query like "from Animal", it does a left outer join for the class Animal,its sub classes and all the associations for Animal and its subclasses. How do i avoid this situation.I want to load the data only when i specify it through a fetchmode in my criteria query?

我正在使用 Hibernate 连接到我的数据库。我的应用程序中有一个继承结构。问题是,当我执行“来自动物”这样的查询时,它会为 Animal 类、其子类以及 Animal 及其子类的所有关联执行左外连接。我如何避免这种情况。我只想在我通过条件查询中的 fetchmode 指定数据时加载数据?

回答by Pascal Thivent

Yes, Hibernate supports polymorphic queries. From the documentation:

是的,Hibernate 支持多态查询。从文档:

14.8. Polymorphic queries

A query like:

from Cat as cat

returns instances not only of Cat, but also of subclasses like DomesticCat. Hibernate queries can name anyJava class or interface in the from clause. The query will return instances of all persistent classes that extend that class or implement the interface. The following query would return all persistent objects:

from java.lang.Object o

The interface Namedmight be implemented by various persistent classes:

from Named n, Named m where n.name = m.name

These last two queries will require more than one SQL SELECT. This means that the order by clause does not correctly order the whole result set. It also means you cannot call these queries using Query.scroll().

14.8. 多态查询

像这样的查询:

from Cat as cat

不仅返回 的实例Cat,还返回像DomesticCat. Hibernate 查询可以在 from 子句中命名任何Java 类或接口。该查询将返回扩展该类或实现该接口的所有持久类的实例。以下查询将返回所有持久对象:

from java.lang.Object o

该接口Named可能由各种持久类实现:

from Named n, Named m where n.name = m.name

最后两个查询将需要多个 SQL SELECT。这意味着 order by 子句没有正确地对整个结果集进行排序。这也意味着您不能使用Query.scroll().

This is the default behavior (called implicitpolymorphism) and Hibernate supports both implicitand explicitpolymorphism:

这是默认行为(称为隐式多态)并且 Hibernate 支持隐式显式多态:

Implicitpolymorphism means that instances of the class will be returned by a query that names any superclass or implemented interface or class, and that instances of any subclass of the class will be returned by a query that names the class itself. Explicitpolymorphism means that class instances will be returned only by queries that explicitly name that class. Queries that name the class will return only instances of subclasses mapped inside this <class>declaration as a <subclass>or <joined-subclass>. For most purposes, the default polymorphism="implicit"is appropriate. Explicit polymorphism is useful when two different classes are mapped to the same table This allows a "lightweight" class that contains a subset of the table columns.

隐式多态意味着类的实例将由命名任何超类或实现的接口或类的查询返回,并且类的任何子类的实例将由命名类本身的查询返回。显式多态意味着类实例只会由明确命名该类的查询返回。命名类的查询将仅返回映射在此<class>声明中的子类的实例 作为 a <subclass><joined-subclass>。对于大多数用途,默认值 polymorphism="implicit"是合适的。当两个不同的类映射到同一个表时,显式多态性很有用 这允许包含表列子集的“轻量级”类。

This can be configured at the class level. Use polymorphism="explicit"if you are if you are using xml mappings, see 5.1.3 Class. Use Hibernate's @Entityannotation if you're using annotations, see 2.4.1. Entity. Below an example:

这可以在类级别进行配置。使用polymorphism="explicit",如果你是,如果你是使用XML映射,请参阅5.1.3类@Entity如果您使用注释,请使用 Hibernate 的注释,请参阅2.4.1。实体。下面是一个例子:

@javax.persistence.Entity
@org.hibernate.annotations.Entity(polymorphism = PolymorphismType.EXPLICIT)
@Inheritance(strategy = InheritanceType.JOINED)
public class Foo {
    ...
}

回答by Manfred

Assume you have a class structure as follows:

假设你有一个类结构如下:

class Animal { }

class Dog : Animal { }

class Cat : Animal { }

then when you select all Animals, you'd expect to also load all Dogs and Cats. After all they are Animals.

那么当您选择所有Animals 时,您还希望加载所有Dogs 和Cats。毕竟他们是Animals。

A different story are the associations. You can created you mappings such that the associations are lazy load instead of eager load.

一个不同的故事是协会。您可以创建映射,使关联是延迟加载而不是急切加载。

回答by Mateusz Dymczyk

Basically it's the default ORM inheritance design pattern used by Hibernate called class inheritance (all the classes are mapped to a single table), if you want to change that you can google:
- single class hierarhy or table per class (this will map every class to a separate table in the DB)
- concrete class hierarhy (this will map only the concrete implementations to a table).

基本上它是 Hibernate 使用的默认 ORM 继承设计模式,称为类继承(所有类都映射到一个表),如果你想改变它,你可以谷歌:
- 单个类层次结构或每个类的表(这将映射每个类到数据库中的一个单独的表)
- 具体的类层次结构(这只会将具体的实现映射到一个表)。

回答by Lukasz Frankowski

To avoid multiple joins during class hierarchy fetching you can apply SINGLE_TABLE hierarchy mapping strategy, and then define secondary tables on subclasses with SELECT fetching strategy. However, this turns you "heavy join" model into "N+1 select" model. The example:

为了避免在类层次结构提取过程中出现多个连接,您可以应用 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;
    }

}

And what SQL is done on from SuperHQL query:

以及对from SuperHQL 查询执行的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

More about this approach and general hibernate performance hints you can read in my article.

您可以在我的文章中阅读有关此方法和一般休眠性能提示的更多信息。