2012-02-14 3 views
1

Учитывая следующий кодJPA Критерии API предикаты для объектов OneToMany отношений

@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 { 

} 

Как бы я написать апи запрос критериев, который возвращает все счета-фактуры с CostLinesItem, что это описание «НАЛОГ»?

Я использую 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-GRAMMER исключение. Псевдоним упоминается в результирующем SQL, который никогда не создается. Похоже, что псевдоним должен был быть привязан к объединению в SQL, который не существует. Другими словами, InvoiceLineItems не запрашиваются в запросе.

ответ

0

Я не в состоянии сделать тест прямо сейчас, но придерживаясь Java EE 6 Tutorial, мы видим, что

вложимых классы могут также содержать отношения к другим лицам или коллекций лиц. Если вложенный класс имеет такое отношение , то отношение относится к целевому объекту или коллекции сущностей для объекта, которому принадлежит вложенный класс.

Это заставляет меня думать, что Join предикат должен быть определен с исходным Entity Invoice вместо InvoiceData. И это подтверждается тем фактом, что обычно исходным Entity должен быть сам корень запроса. Я хотел бы попробовать что-то вроде этого:

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

Благодарим за информацию. Если я не ошибаюсь, в настоящее время это предлагается (за исключением JoinType.LEFT, который я добавил во время борьбы)? – fransvn

0

я выгружена гибернации 4.1.0.Final для EclipseLink 2.0.0, и она работала.

Смежные вопросы