HIbernate加载子类和类

时间:2010-08-05 08:19:07

标签: java hibernate orm

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

4 个答案:

答案 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时,您还希望加载所有DogCat 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