2 years ago
#61448
jansohn
CriteriaAPI + subquery creates wrong SQL (invalid identifier)
Not sure what I'm dong wrong so I'm guessing this is a bug. I'm trying to create a simple subquery but Eclipselink produces wrong SQL so the execution fails.
Error message
[EL Warning]: 2022-01-17 17:00:29.258--UnitOfWork(1407952056)--Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.6.9.v20200130-0143b822bc): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLSyntaxErrorException: ORA-00904: "T1"."ID"."T1"."ID": invalid identifier
Error Code: 904
Call: SELECT COUNT(t0.ID) FROM Order t0 WHERE t0.OUTPUT IN (SELECT t1.ID.t1.ID FROM Process t1 WHERE (t1.OWNER = ?))
bind => [0]
Query: ReportQuery(referenceClass=Order sql="SELECT COUNT(t0.ID) FROM Order t0 WHERE t0.OUTPUT IN (SELECT t1.ID.t1.ID FROM Process t1 WHERE (t1.OWNER = ?))")
Sample code
EntityManager em = ApplicationContextListener.createEntityManager();
try {
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Long> cq = cb.createQuery(Long.class);
Root<Order> root = cq.from(Order.class);
cq.select(cb.count(root));
// Process subquery
Subquery<Long> sqProcess = cq.subquery(Long.class);
Root<Process> sqProcessRoot = sqProcess.from(Process.class);
Path<Long> processId = sqProcessRoot.get("id");
sqProcess.select(processId)
.where(cb.equal(sqProcessRoot.get("owner"), cb.parameter(String.class, "person")));
cq.where(cb.in(root.get("processOutput")).value(sqProcess));
TypedQuery<Long> tq = em.createQuery(cq);
int count = tq.setParameter("person", loggedInPerson).getSingleResult().intValue();
log.debug("SQL count string: {}", tq.unwrap(JpaQuery.class).getDatabaseQuery().getSQLString());
log.debug("Count = {}", count);
} finally {
em.close();
}
Order
@Entity
@Table(name = "Order")
public class Order implements Serializable {
private static final long serialVersionUID = 2804475880693788686L;
@Id
@SequenceGenerator(name = "ORDER_ID_GENERATOR", sequenceName = "ORDER_SEQ", allocationSize = 1, initialValue = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ORDER_ID_GENERATOR")
private long id;
// bi-directional many-to-one association to Process
@ManyToOne
@JoinColumn(name = "OUTPUT")
private Process processOutput;
public long getId() {
return this.id;
}
public void setId(long id) {
this.id = id;
}
public Process getProcessOutput() {
return this.processOutput;
}
public void setProcessOutput(Process processOutput) {
this.processOutput = processOutput;
}
}
Process
@Entity
@Table(name = "Process")
public class Process implements Serializable {
private static final long serialVersionUID = -2021620806203228247L;
@Id
@SequenceGenerator(name = "PROCESS_ID_GENERATOR", sequenceName = "PROCESS_SEQ", allocationSize = 1, initialValue = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "PROCESS_ID_GENERATOR")
@Expose
private long id;
@ManyToOne
@JoinColumn(name = "OWNER")
private Person owner;
@XmlTransient
public long getId() {
return this.id;
}
public void setId(long id) {
this.id = id;
}
public Person getOwner() {
return owner;
}
public void setOwner(Person owner) {
this.owner = owner;
}
}
jpa
eclipselink
jpql
criteria-api
0 Answers
Your Answer