没有连接的QueryDSL Access Id列

时间:2017-10-04 12:16:49

标签: hibernate querydsl hibernate-envers

描述

我们有一个案例,我们要查询历史信息,我们想使用QueryDSL而不是原始SQL。历史表中的数据包含原始记录的ID(Hibernate ENVERs),如果删除,则删除实际记录,但ENVER记录包含原始ID。

问题

我们面临的问题是,由于创建Q类的实体仅引用外键,因此强制在SQL中进行连接。由于使用了Hibernate,我们无法为多个字段引用该列。

我们希望QueryDSL能够在不执行连接的情况下引用原始id列,并且不会将实体本身更改为仅包含ID而不是映射到Foo的引用。

数据\示例(伪代码)

实体

@Entity
@Table=name = "foo")
public class Foo {
    @Id
    @Column(name = "foo_id", nullable = false)
    private Long fooId;

}

@Entity
@Table=name = "foo_bar")
public class FooBar {
    @Id
    @Column(name = "foo_bar_id", nullable = false)
    private Long fooBarId;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "foo_id")
    private Foo foo;
}

强制查询

HibernateQuery dsl = createHibernateQuery();
dsl
    .from(qFooBar)
    .where(qFooBar.foo.fooId.eq(id))
;

理想查询

HibernateQuery dsl = createHibernateQuery();
dsl
    .from(qFooBar)
    .where(qFooBar.fooId.eq(id))
;

其他信息

在现实世界的用例中,查询要复杂得多,因此我们无法使用纯粹的ENVERs API进行查询。

版本

  • Spring:4.2.8.RELEASE
  • Hibernate:4.3.11.Final
  • QueryDSL:3.7.4
  • Java 7

1 个答案:

答案 0 :(得分:1)

我无法说出QueryDSL;但是,传统的Envers API确实为您提供了开箱即用的功能。

鉴于您的示例基于关联的标识符,您可以使用relatedId谓词来实现您的目标:

List results = auditReader.createQuery()
    .forRevisionsOfEntity( FooBar.class, true, false )
    .add( AuditEntity.relatedId( "foo" ).eq( fooId ) )
    .getResultList();

这将返回审核历史记录中的所有FooBar个实例(不包括删除),其中FooBar与使用标识符Foo的{​​{1}}相关。

此处唯一的限制是查询必须仅基于关联标识符应用限制,而不是基于非标识符的属性。

当我们引入Envers Query遍历API时,询问哪个版本是因为在5.2.x分支中的原因,它扩展了查询API,提供了基于实体层次结构中任何位置的任何一对一关联属性应用谓词的方法。

例如,以下内容显示了定位fooId个实体,相关FooBar上的某些随机属性为Foo

someValue

因此,除非存在特定用例,否则您无法使用Envers查询API完成查询,我不相信您对QueryDSL库的使用是必要的,并且本机List results = auditReader.createQuery() .forRevisionsOfEntity( FooBar.class, true, false ) .traverseRelation( "foo", JoinType.INNER ) .add( AuditEntity.property( "somePropertyOnFoo" ).eq( someValue ) ) .up() .getResultList(); 接口提供所有你需要的工具。