Reputation: 609
While this JPQL is working without any exception
Query query = em.createQuery("SELECT DISTINCT(r) FROM Request r LEFT JOIN Requesthistory h
WHERE h.request = r
AND (r.responsible = :employee OR h.employee = :employee)
AND r.requestedby != :employee ORDER BY r.objid DESC");
this JPQL is not working and throws NullPointerException
Query query = em.createQuery("SELECT DISTINCT(r) FROM Request r LEFT JOIN Requesthistory h
ON h.request = r
WHERE (r.responsible = :employee OR h.employee = :employee)
AND r.requestedby != :employee ORDER BY r.objid DESC");
The only difference between these two JPQL is ON Clause.
And yes there is 1:N relation between Request and Requesthistory in both entities and tables.
Here is exception I got:
Exception Description: Query failed to prepare, unexpected error occurred: [java.lang.NullPointerException].
Internal Exception: java.lang.NullPointerException
Query: ReportQuery(referenceClass=Request jpql="SELECT DISTINCT(r) FROM Request r LEFT JOIN Requesthistory h ON h.request = r WHERE (r.responsible = :employee OR h.employee = :employee) AND r.requestedby != :employee ORDER BY r.objid DESC")
at org.eclipse.persistence.exceptions.QueryException.prepareFailed(QueryException.java:1590) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.queries.DatabaseQuery.checkPrepare(DatabaseQuery.java:680) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.queries.ObjectLevelReadQuery.checkPrepare(ObjectLevelReadQuery.java:901) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.queries.DatabaseQuery.checkPrepare(DatabaseQuery.java:613) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.buildEJBQLDatabaseQuery(EJBQueryImpl.java:194) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.buildEJBQLDatabaseQuery(EJBQueryImpl.java:116) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.<init>(EJBQueryImpl.java:102) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.<init>(EJBQueryImpl.java:86) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.createQuery(EntityManagerImpl.java:1603) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at com.kadir.dao.notification.RequestDao.findToUserRequests(RequestDao.java:44) [classes:]
at com.kadir.service.notification.RequestService.getToUserRequests(RequestService.java:43) [classes:]
at com.kadir.bean.notification.RequestBean.init(RequestBean.java:49) [classes:]
... 110 more
Caused by: java.lang.NullPointerException
at org.eclipse.persistence.internal.expressions.ObjectExpression.getOwnedTables(ObjectExpression.java:583) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.internal.expressions.FieldExpression.validateNode(FieldExpression.java:294) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.expressions.Expression.normalize(Expression.java:3275) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.internal.expressions.DataExpression.normalize(DataExpression.java:369) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.internal.expressions.FieldExpression.normalize(FieldExpression.java:223) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.internal.expressions.CompoundExpression.normalize(CompoundExpression.java:224) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.internal.expressions.RelationExpression.normalize(RelationExpression.java:574) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.internal.expressions.RelationExpression.normalize(RelationExpression.java:865) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.expressions.ExpressionBuilder.normalize(ExpressionBuilder.java:267) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.internal.expressions.RelationExpression.normalize(RelationExpression.java:825) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.internal.expressions.CompoundExpression.normalize(CompoundExpression.java:232) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.internal.expressions.CompoundExpression.normalize(CompoundExpression.java:224) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.internal.expressions.SQLSelectStatement.normalize(SQLSelectStatement.java:1449) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.buildReportQuerySelectStatement(ExpressionQueryMechanism.java:641) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.buildReportQuerySelectStatement(ExpressionQueryMechanism.java:586) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.prepareReportQuerySelectAllRows(ExpressionQueryMechanism.java:1694) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.queries.ReportQuery.prepareSelectAllRows(ReportQuery.java:1203) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.queries.ReadAllQuery.prepare(ReadAllQuery.java:744) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.queries.ReportQuery.prepare(ReportQuery.java:1071) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
at org.eclipse.persistence.queries.DatabaseQuery.checkPrepare(DatabaseQuery.java:661) [eclipselink.jar:2.5.2.v20140319-9ad6abd]
... 120 more
What am I doing wrong?
UPDATE FOR ENTITIES
Request.java
package com.kadir.entity.notification;
import com.kadir.entity.Base;
import com.kadir.entity.humanresource.Employee;
import java.io.Serializable;
import javax.persistence.*;
import java.util.List;
/**
* The persistent class for the REQUEST database table.
*
*/
@Cacheable
@Entity
@Table(name="REQUEST", schema="NOTIFICATION")
@NamedQuery(name="Request.findAll", query="SELECT r FROM Request r")
public class Request extends Base implements Serializable {
private static final long serialVersionUID = 1L;
@Column(name="CONTENT")
private String content;
@ManyToOne
@JoinColumn(name="REQUESTEDBY")
private Employee requestedby;
@ManyToOne
@JoinColumn(name="RESPONSIBLEOBJID")
private Employee responsible;
@Column(name="TITLE")
private String title;
//bi-directional many-to-one association to Requesttype
@ManyToOne
@JoinColumn(name="REQUESTTYPEOBJID")
private Requesttype requesttype;
//bi-directional many-to-one association to Responsetype
@ManyToOne
@JoinColumn(name="RESPONSETYPEOBJID")
private Responsetype responsetype;
//bi-directional many-to-one association to Requesthistory
@OneToMany(mappedBy="request")
private List<Requesthistory> requesthistories;
public Request() {
}
public String getContent() {
return this.content;
}
public void setContent(String content) {
this.content = content;
}
public Employee getRequestedby() {
return this.requestedby;
}
public void setRequestedby(Employee requestedby) {
this.requestedby = requestedby;
}
public Employee getResponsible() {
return this.responsible;
}
public void setResponsible(Employee responsible) {
this.responsible = responsible;
}
public String getTitle() {
return this.title;
}
public void setTitle(String title) {
this.title = title;
}
public Requesttype getRequesttype() {
return this.requesttype;
}
public void setRequesttype(Requesttype requesttype) {
this.requesttype = requesttype;
}
public Responsetype getResponsetype() {
return this.responsetype;
}
public void setResponsetype(Responsetype responsetype) {
this.responsetype = responsetype;
}
public List<Requesthistory> getRequesthistories() {
return this.requesthistories;
}
public void setRequesthistories(List<Requesthistory> requesthistories) {
this.requesthistories = requesthistories;
}
public Requesthistory addRequesthistory(Requesthistory requesthistory) {
getRequesthistories().add(requesthistory);
requesthistory.setRequest(this);
return requesthistory;
}
public Requesthistory removeRequesthistory(Requesthistory requesthistory) {
getRequesthistories().remove(requesthistory);
requesthistory.setRequest(null);
return requesthistory;
}
}
RequestHistory.java
package com.kadir.entity.notification;
import com.kadir.entity.humanresource.Employee;
import com.kadir.entity.Base;
import java.io.Serializable;
import javax.persistence.*;
/**
* The persistent class for the REQUESTHISTORY database table.
*
*/
@Cacheable
@Entity
@Table(name="REQUESTHISTORY", schema="NOTIFICATION")
@NamedQuery(name="Requesthistory.findAll", query="SELECT r FROM Requesthistory r")
public class Requesthistory extends Base implements Serializable {
private static final long serialVersionUID = 1L;
@ManyToOne
@JoinColumn(name="EMPLOYEEOBJID")
private Employee employee;
@Column(name="EXPLANATION")
private String explanation;
//bi-directional many-to-one association to Request
@ManyToOne
@JoinColumn(name="REQUESTOBJID")
private Request request;
//bi-directional many-to-one association to Responsetype
@ManyToOne
@JoinColumn(name="RESPONSETYPEOBJID")
private Responsetype responsetype;
public Requesthistory() {
}
public Employee getEmployee() {
return this.employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
public String getExplanation() {
return this.explanation;
}
public void setExplanation(String explanation) {
this.explanation = explanation;
}
public Request getRequest() {
return this.request;
}
public void setRequest(Request request) {
this.request = request;
}
public Responsetype getResponsetype() {
return this.responsetype;
}
public void setResponsetype(Responsetype responsetype) {
this.responsetype = responsetype;
}
}
Base.java
package com.kadir.entity;
import java.math.BigInteger;
import java.sql.Timestamp;
import java.util.Date;
import javax.persistence.Cacheable;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.persistence.Version;
@Cacheable
@MappedSuperclass
public abstract class Base {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "OBJID")
private BigInteger objid;
@Column(name = "CREATEDBY")
private String createdby;
@Column(name = "CREATEDDATE")
private Timestamp createddate;
@Version
@Column(name = "ROWVERSION")
private Integer rowversion;
@Column(name = "UPDATEDBY")
private String updatedby;
@Column(name = "UPDATEDDATE")
private Timestamp updateddate;
@Column(name = "ARCHIVED", columnDefinition = "int default 0")
private int archived;
public BigInteger getObjid() {
return this.objid;
}
public void setObjid(BigInteger objid) {
this.objid = objid;
}
public String getCreatedby() {
return this.createdby;
}
public void setCreatedby(String createdby) {
this.createdby = createdby;
}
public Date getCreateddate() {
return this.createddate;
}
public void setCreateddate(Timestamp createddate) {
this.createddate = createddate;
}
public Integer getRowversion() {
return this.rowversion;
}
public void setRowversion(Integer rowversion) {
this.rowversion = rowversion;
}
public String getUpdatedby() {
return this.updatedby;
}
public void setUpdatedby(String updatedby) {
this.updatedby = updatedby;
}
public Timestamp getUpdateddate() {
return this.updateddate;
}
public void setUpdateddate(Timestamp updateddate) {
this.updateddate = updateddate;
}
public int getArchived() {
return archived;
}
public void setArchived(int archived) {
this.archived = archived;
}
}
Upvotes: 0
Views: 1515
Reputation: 1489
I think problem is with your inheritance mapping.
The mapped supperclass Base
has no inheritance strategy defined, so default one SINGLE_TABLE is used. Next you define @Table(name="...")
annotations on each of your sublcasses Request
and Requesthistory
what makes no sense with SINGLE_TABLE strategy as with this strategy all subclasses are mapped to one shared table.
I think TABLE_PER_CLASS is the strategy you want.
@Cacheable
@MappedSuperclass
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Base {
In jpql join clauses are used a little bit different as in sql. You can not join arbitrary entities and then bind them through ON or WHERE clause. You can join only entities associated in abstract schema.
Try following (jpql valid) query:
SELECT DISTINCT(r)
FROM Request r
LEFT JOIN r.requesthistories h
WHERE (r.responsible = :employee OR h.employee = :employee)
AND r.requestedby != :employee
ORDER BY r.objid DESC
(Note: Queries over non-associated entities are posssible, but it is different topic.)
Upvotes: 2