【问题标题】:How to refer to a subclass specific field in a CriteriaQuery where the super class is queried?如何在查询超类的 CriteriaQuery 中引用子类特定字段?
【发布时间】:2013-06-07 03:54:16
【问题描述】:

我正在尝试使用 JPA Criteria API 实现以下目标:

SELECT b FROM Box b JOIN SpecialItem s WHERE s.specialAttr = :specialAttr

对象是

盒子

@Entity
public class Box implements Serializable {
  ...
  @ManyToOne
  @JoinColumn( name = "item_id" )
  Item item;
  ...
}

物品

@Entity
@Inheritance( strategy = InheritanceType.JOINED )
public class Item implements Serializable {
  @Id
  private String id;
  ...
}

特殊物品

@Entity
public class SpecialItem extends Item {
  private String specialAttr;
  ...
}

我的尝试

EntityManager em = getEntityManager();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery cq = cb.createQuery( Box.class );
Root from = cq.from( Box.class );

// Nothing to specify SpecialItem over Item!      
Join join = from.join("item", JoinType.LEFT);

// java.lang.IllegalArgumentException: Unable to 
// resolve attribute [specialAttr] against path [null]      
Path p = join.get( "specialAttr" );

Predicate predicate = cb.equal( p, "specialValue" );
cq.where( predicate );

毫不奇怪,它会引发异常,因为 specialAttr 不是 Item 类的成员。

如何返回所有包含SpecialItemBoxes,其中SpecialItem.specialAttr 有一些价值?

【问题讨论】:

  • 我的问题是如何返回包含SpecialItem TOO 的Boxes?很高兴收到您的来信。

标签: jpa criteria-api


【解决方案1】:

如果使用 JPA 2.1,您可能会使用

"SELECT b FROM Box b WHERE TREAT(b.item as SpecialItem).specialAttr = :specialAttr"

CriteriaQuery<Box> q = cb.createQuery(Box.class);
Root<Box> box= q.from(Box.class);
Join<Box, Item > order = box.join("item");
q.where(cb.equal(cb.treat(order, SpecialItem.class).get("specialAttr"),
    qb.parameter(String.class, "specialAttr")));
q.select(Box);

【讨论】:

  • 谢谢,但我将如何使用 Criteria API 做到这一点?
  • 非常感谢!如果有兴趣,可以使用 JPA 2.0 解决吗?
  • 是的,但是以一种可能会导致额外连接的方式出现。您需要在连接中明确,并以相反的方式构建查询。类似于“从 Box b 中选择 b,SpecialtyItem si where b.item = si and si.specialAttr = :specialAttr”
【解决方案2】:

我只是想用生成的元模型扩展 Chris 对 Criteria API 的回答。

CriteriaQuery<Box> q = cb.createQuery(Box.class);
Root<Box> box= q.from(Box.class);
Join<Box, Item> order = box.join(Box_.item);
q.where(cb.equal(cb.treat(order, SpecialItem.class).get(SpecialItem_.specialAttr), "searchValue");
q.select(Box);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-03
    • 1970-01-01
    • 2017-04-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多