如何在jpaql或hql查询中使用复合键中的单列

时间:2013-05-08 22:48:45

标签: hibernate jpa composite-key

提供者是hibernate 3.6。

我有一个通过@IdClass声明的复合键,由4列组成。当通过完整的主键存储和检索实体实例时,一切正常。但是,如果我希望查询只有一列中具有特定值的所有实体,则hibernate会抛出异常。

@Entity
@IdClass(MyBeanId.class)
public class MyBean {
    @Id
    private Integer partId1;
    @Id
    private Integer partId2;
    @Id
    private Integer partId3;
    @Id
    private String partId4;
    private Integer otherProperty1;
    private Double otherProperty2;
    private Double otherProperty3;
    private String otherProperty4;

        /* removed getters and setters */
}

在另一个类中查询代码:

public List<MyBean> findByPartId1(Integer partId1) {
    return em.createQuery("select b from MyBean b where b.partId1 = :partId1", MyBean.class).setParameter("partId1", partId1).getResultList();
}

另一个失败的查询,以及关于不知道参数类型的错误消息如下:

public List<Integer> getAllPartId1s() {
    return em.createQuery("select distinct b.partId1 from MyBean b", Integer.class).getResultList();
}

我从第一个查询获得的异常如下:

Caused by: org.hibernate.QueryException: could not resolve property: partId1 of: some.company.entity.MyBean [select t from some.company.entity.MyBean b where b.partId1 = :partId1]
    at org.hibernate.persister.entity.AbstractPropertyMapping.propertyException(AbstractPropertyMapping.java:81)
    at org.hibernate.persister.entity.AbstractPropertyMapping.toType(AbstractPropertyMapping.java:75)
    at org.hibernate.persister.entity.AbstractEntityPersister.toType(AbstractEntityPersister.java:1465)
    at org.hibernate.hql.ast.tree.FromElementType.getPropertyType(FromElementType.java:315)
    at org.hibernate.hql.ast.tree.FromElement.getPropertyType(FromElement.java:487)
    at org.hibernate.hql.ast.tree.DotNode.getDataType(DotNode.java:611)
    at org.hibernate.hql.ast.tree.DotNode.prepareLhs(DotNode.java:263)
    at org.hibernate.hql.ast.tree.DotNode.resolve(DotNode.java:210)
    at org.hibernate.hql.ast.tree.FromReferenceNode.resolve(FromReferenceNode.java:117)
    at org.hibernate.hql.ast.tree.FromReferenceNode.resolve(FromReferenceNode.java:113)
    at org.hibernate.hql.ast.HqlSqlWalker.resolve(HqlSqlWalker.java:880)
    at org.hibernate.hql.antlr.HqlSqlBaseWalker.expr(HqlSqlBaseWalker.java:1330)
    at org.hibernate.hql.antlr.HqlSqlBaseWalker.exprOrSubquery(HqlSqlBaseWalker.java:4471)
    at org.hibernate.hql.antlr.HqlSqlBaseWalker.comparisonExpr(HqlSqlBaseWalker.java:3944)

当然,有一些方法可以在查询中访问复合键的各个列,而无需使用@Embeddable id对象?否则,为什么甚至有@IdClass机制,因为它几乎没用。我尝试了很多变种,例如“where b.id.partId1 =:partId1”但它们都失败了。

是的,我有一个具有相同属性的MyBeanId类和一个有效的hashCode和equals,但是为了发布问题我只想清理那么多代码。

1 个答案:

答案 0 :(得分:1)

我知道现在回答您的查询为时已晚(3年后)。此外,我使用的方式使用@EmbeddedId而不是@IdClass但只是认为它可能会帮助那些可能在这里寻找类似问题答案的其他人。

您可以将包含复合键的所有字段放在不同的类中,如下所示:

@Embeddable
public class MyBeanId {
private Integer partId1;

private Integer partId2;

private Integer partId3;

private String partId4;
}

在您的实体中使用该类:

public class MyBean {
 @EmbeddedId
 private MyBeanId id;
 // other attrbute goes here
}

然后将查询写为:

public List<Integer> getAllPartId1s() {
  return em.createQuery("select distinct b.id.partId1 from MyBean b"....
}