给出以下代码
@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中的连接。换句话说,查询中不会提取InvoiceLineItems。
我现在无法进行测试,但坚持使用Java EE 6 Tutorial,我们看到了
可嵌入类还可以包含与其他实体或实体集合的关系。如果可嵌入类具有这种关系,则关系是从目标实体或实体集合到拥有可嵌入类的实体。
这让我认为Join
谓词应该用起始实体Invoice
而不是InvoiceData
来定义。这也得益于通常起始实体应该是查询根本身。我会尝试这样的事情:
Join<Invoice, InvoiceLineItem> lineItems = root.join(Invoice_.data).join(InvoiceData_.lineItems);
我为EclipseLink 2.0.0换了Hibernate 4.1.0.Final并且它运行了。