What I need to get are all Events where CustomerEvent.customer.id = 123. What I actually get is exception.

Simplified entities with relevant members only:

@Table(name = "EVENT")
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "TYPE", discriminatorType = DiscriminatorType.STRING, length = 1)
public abstract class Event {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(nullable = false)
    private Integer id;
}

@Entity
@DiscriminatorValue("C")
public class CustomerEvent extends Event {
    @ManyToOne(optional = false)
    private Customer customer;
}

@Entity
@Table(name = "CUSTOMER")
public class Customer {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(nullable = false)
    private Integer id;

}

Query:

final CriteriaBuilder cb = em.getCriteriaBuilder();
final CriteriaQuery<Event> cq = cb.createQuery(Event.class);
final Root<Event> root = cq.from(Event.class);
cq.select(root);
cq.where(cb.equal(((Root<CustomerEvent>) root.as(CustomerEvent.class)).get(CustomerEvent_.customer).get(Customer_.id), 123));

// this predicate doesn't work either: cb.isNotNull(((Root<CustomerEvent>) root.as(CustomerEvent.class)).get(CustomerEvent_.customer));

em.createQuery(cq).getResultList(); // throws exception

Exception:

Exception [EclipseLink-6015] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.QueryException
Exception Description: Invalid query key [customer] in expression.
Query: ReadAllQuery(referenceClass=Event )
    at org.eclipse.persistence.exceptions.QueryException.invalidQueryKeyInExpression(QueryException.java:691)
有帮助吗?

解决方案

If you are using root.as(CustomerEvent.class), why not just query on CustomerEvent? Only CustomerEvent instances can have CustomerEvent.customer.id = 123 or you wouldn't need to use the 'as' function.

'As' was deprecated and JPA's Treat predicate (included in EclipseLink 2.5.1) should be used instead - the difference is that treat will exclude non-customerEvent instances within that predicate while 'as' only cast the predicate, and so was more difficult to use and not as stable. Treat allows you to safely use more complex expressions such as "Select event from Event event where (treat(event as CustomerEvent).customer.id = 123) or event.somethingelse = someotherCondition"

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top