如何在Hibernate查询属性可能为null或特定值的对象?

时间:2012-07-25 16:08:46

标签: spring hibernate criteria

我正在使用以下对象:

RawRead RawRead.Checkpoint

Checkpoint.EndCustomer

保护

Checkpoint和Guard是RawRead的属性,EndCustomer是Checkpoint的属性。一切都是对象。


我目前的Hibernate gubbins:

Criteria crit = sess.createCriteria(RawRead.class);
crit.add(
  Restrictions.or(
    Restrictions.eq("checkpoint", null),
    Restrictions.in("checkpoint.parentEndCustomer",collectionOfEndCustomers)
  )
);

因此Checkpoint可以为null,但如果它在那里我只想要parentRend对象在parentpoint.parentEndCustomer属性中的RawRead对象。

我希望这是有道理的。


我上面的猜测会产生一个错误(对我来说)表明我的标准被错误地指定了:

[Request processing failed; nested exception is org.hibernate.QueryException: could not resolve property: checkpoint.parentEndCustomer of: uk.co.romar.guardian.objects.RawRead] with root cause org.hibernate.QueryException: 
could not resolve property: checkpoint.parentEndCustomer of: uk.co.romar.guardian.objects.RawRead at 
org.hibernate.persister.entity.AbstractPropertyMapping.propertyException(AbstractPropertyMapping.java:81) at 
org.hibernate.persister.entity.AbstractPropertyMapping.toColumns(AbstractPropertyMapping.java:96)   at  
org.hibernate.persister.entity.BasicEntityPropertyMapping.toColumns(BasicEntityPropertyMapping.java:62) at 
org.hibernate.persister.entity.AbstractEntityPersister.toColumns(AbstractEntityPersister.java:1457) at 
org.hibernate.loader.criteria.CriteriaQueryTranslator.getColumns(CriteriaQueryTranslator.java:483)

RawRead的相关位:

@ManyToOne
@JoinColumn(name="CHECKPOINT_OID")
@NotFound(action=NotFoundAction.IGNORE)
public Checkpoint checkpoint = null;
public void setCheckpoint(Checkpoint in) {this.checkpoint = in;}
public Checkpoint getCheckpoint() {return this.checkpoint;}

@ManyToOne
@JoinColumn(name="GUARD_OID")
@NotFound(action=NotFoundAction.IGNORE)
private Guard guard = null;
public void setGuard(Guard in) {this.guard = in;}
public Guard getGuard() {return this.guard;}

来自Checkpoint:

    @ManyToOne
@JoinColumn(name="ENDCUSTOMER_OID")
@NotFound(action=NotFoundAction.IGNORE)
private EndCustomer parentEndCustomer = null;
public EndCustomer getParentEndCustomer() {return this.parentEndCustomer;}
public void setParentEndCustomer(EndCustomer ownerCustomer) {this.parentEndCustomer = ownerCustomer;}

编辑从下面实施第一个答案后跟进。

如果我在数据库中有这样的数据(我希望符号有意义!):

RawRead {
 ID=1
 checkpoint={id=1,parentEndCustomer={ID=1}}
}
RawRead {
 ID=2
 checkpoint={id=4,parentEndCustomer={ID=4}}
}
RawRead {
 ID=3
 checkpoint={id=7,parentEndCustomer={ID=31}}
}
RawRead {
 ID=4
 checkpoint={null}
}

和Restriction中给出的collectionOfEndCustomers是这样的: EndCustomer = {ID = 31}

我想要只检索RawReads 3和4。 RawRead 1& 2被拒绝,因为子检查点属性的parentEndCustomer与传入collectionOfEndCustomers中的限制的parentEndCustomer不匹配。

应该选择RawRead.3,因为parentEndCustomer与传入的集合中的一个匹配。应该选择RawRead.4,因为检查点为空。

按照下面第一个答案中的指导导致返回上述所有RawReads而不是我之后的子集。

1 个答案:

答案 0 :(得分:2)

您不能像在HQL中那样链接属性。您必须使用条件的连接。由于检查点可以为null,因此必须使用左连接。此外,Restrictions.eq()不能用于与null进行比较(如在HQL和SQL中)。您必须使用Restrictions.isNull()来执行此操作。

所以你的查询应该是这样的:

Criteria crit = sess.createCriteria(RawRead.class, "rawRead");
crit.createAlias("rawRead.checkpoint", "checkpoint", Criteria.LEFT_JOIN)
crit.add(
    Restrictions.or(
        Restrictions.isNull("checkpoint.id"),
        Restrictions.in("checkpoint.parentEndCustomer", collectionOfEndCustomers)
    )
);