一尘不染

如何编写超类的Hibernate Criteria查询,并检查某些子类?

hibernate

如何编写超类的Hibernate Criteria查询,并检查某些子类?假设我们有以下所有类都通过Hibernate-JPA映射:

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class Bar {
    @Id
    @Column(name = "id")
    private Long id;
}

@Entity
@PrimaryKeyJoinColumn(name="bar_id")
public class Foo extends Bar {
}

@Entity
@PrimaryKeyJoinColumn(name="bar_id")    
public class Goo extends Bar {
}

当编写这样的Criteria查询时,出于性能考虑,我希望对子类使用左联接:

getSession()
    .createCriteria(Bar.class)
    .createAlias("Foo", "foo", CriteriaSpecification.LEFT_JOIN)
    .add(Restrictions.isNotNull("foo.bar_id"))
    .list();

这失败了,因为关联路径“
Foo”显然不起作用,但是它将说明我想要的。还是有另一种方式进行这种查询?我需要在超类上执行查询。如果我会用SQL完成它,它将看起来像这样:

select b.*
from bar b left join foo f on f.bar_id = b.id
where f.bar_id is not null;

上面的SQL查询只是为了说明我的意思,我知道在这种特定情况下使用“普通”联接会更容易。


阅读 206

收藏
2020-06-20

共1个答案

一尘不染

确实不清楚您想做什么。

首先,由于Foo继承自Bar,因此搜索Bar实例将自动返回Foo实例。Hibernate自己负责连接表。

第二:您的SQL查询确实很奇怪。您正在执行左联接(这意味着您正在搜索可能没有关联的foo的小节),但是foo.bar_id上的close位置也不为空。实际上,这构成了内部联接,可以重写为

select b.* from bar b inner join foo f on f.bar_id = b.id

如果您要搜索的是Foos,并且仅搜索Foos,则使用以Foo为根实体的条件:

getSession()
    .createCriteria(Foo.class)
    .list();

您将获得Foo实例,但是由于Foo扩展了Bar,因此这些Foo实例也是Bar实例。那就是继承。

现在,如果您要动态构建Criteria实例,并且意识到搜索必须只返回Foo实例,则必须使用隐式类属性:

Criteria c = getSession().createCriteria(Bar.class, "bar")
// ...
if (limitToFoos) {
    c.add(Restrictions.eq("bar.class", Foo.class));
}
2020-06-20