JPA Criteria API预测OneToMany关系中的对象

时间:2012-02-14 17:09:01

标签: jpa jpa-2.0 criteria criteria-api

给出以下代码

@Entity
public class Invoice {

  @GeneratedValue(strategy = GenerationType.AUTO)
  @Id
  public Long id;

  @Embedded
  private InvoiceData data = new InvoiceData();
} 


@Embeddable
public class InvoiceData {
  @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
  public Collection<InvoiceLineItem> lineItems;
}

@Entity
public abstract class InvoiceLineItem {

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private Long id;

  @Column
  private String description;
}

@Entity
public class GoodsLineItem extends InvoiceLineItem {

}

@Entity
public class CostLineItem extends InvoiceLineItem {

}

我如何编写一个标准api查询,该查询返回所有带有CostLinesItem的发票,其描述为'TAX'?

我正在使用元数据API。我尝试了各种方法,其中大部分是下面列出的2的变体。任何指针/帮助或'去读这个都将非常感谢。

尝试1(很多):

@Test
public void criteria_api_and_collections() throws Exception {

    CriteriaBuilder builder = em.getCriteriaBuilder();
    CriteriaQuery<Invoice> query = builder.createQuery(Invoice.class);
    Root<Invoice> root = query.from(Invoice.class);

    Join<InvoiceData, InvoiceLineItem> lineItems = root.join(Invoice_.data).join(InvoiceData_.lineItems);

    query.where(builder.equal(lineItems.get(InvoiceLineItem_.description), ""));
    List<Invoice> resultList = em.createQuery(query).getResultList();

    System.out.println(resultList);
}

尝试2(很多人):

@Test
public void criteria_api_and_collections() throws Exception {

    CriteriaBuilder builder = em.getCriteriaBuilder();
    CriteriaQuery<Invoice> query = builder.createQuery(Invoice.class);
    Root<Invoice> root = query.from(Invoice.class);

    Join<InvoiceData, InvoiceLineItem> lineItems = root.join(Invoice_.data).join(InvoiceData_.lineItems, JoinType.LEFT);

    Subquery<CostLineItem> subquery = query.subquery(CostLineItem.class);
    Root<CostLineItem> fromLineItem = subquery.from(CostLineItem.class);
    subquery.select(fromLineItem);
    subquery.where(builder.equal(lineItems.get(InvoiceLineItem_.description), "TAX"));

    query.where(builder.in(lineItems).value(subquery));

    List<Invoice> resultList = em.createQuery(query).getResultList();
}

两次尝试都会导致SQL语法异常。在结果SQL中引用别名,该别名从未创建。看起来应该将别名分配给不存在的SQL中的连接。换句话说,查询中不会提取InvoiceLineItem。

2 个答案:

答案 0 :(得分:0)

我现在无法进行测试,但坚持Java EE 6 Tutorial,我们看到了

  

可嵌入类也可能包含与其他实体的关系或   实体集合。如果嵌入类有这样的   关系,关系来自目标实体或集合   实体到拥有可嵌入类的实体。

这使我认为应该使用起始实体Join而不是Invoice来定义InvoiceData谓词。这也得益于通常起始实体应该是查询根本身。我会尝试这样的事情:

Join<Invoice, InvoiceLineItem> lineItems = root.join(Invoice_.data).join(InvoiceData_.lineItems);

答案 1 :(得分:0)

我为EclipseLink 2.0.0换了Hibernate 4.1.0.Final并且它运行了。