Thursday, April 19, 2012

OpenJPA - id field of an instance is returning null on query

I am using Apache CXF (version 2.5.2) to implement REST services that do add, update, delete, query single and list of records on database tables. I am using OpenJPA (version 2.2.0) in the persistence layer.



As an example, I have a table named Complaint, mapped to an entity class of the same name. The complaint entity is similar to this:



import java.io.Serializable;
import java.sql.Timestamp;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;



/**
* The persistent class for the "Complaint" database table.
*
*/
@Entity
@Table(name = "Complaint")
@NamedQueries({
@NamedQuery(name = "cmplById", query = "SELECT c FROM Complaint c WHERE c.id = ?1"),
@NamedQuery(name = "cmplBySearchCriteria", query = "SELECT c FROM Complaint c WHERE c.status = ?1 AND c.category = ?2 AND c.location = ?3 AND "
+ "c.reportDate BETWEEN ?4 AND ?5 ORDER BY c.id DESC")

})

public class Complaint implements Serializable {
private static final long serialVersionUID = 1L;

private Integer id;

private String description;

private String location;

private Timestamp reportDate;

private String reportedBy;

private String status;

private String category;

public Complaint() {
}

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "Id", nullable = false)
public Integer getId() {
return this.id;
}

public void setId(Integer id) {
this.id = id;
}

@Column(name = "Description")
public String getDescription() {
return this.description;
}

public void setDescription(String description) {
this.description = description;
}

@Column(name = "Location")
public String getLocation() {
return this.location;
}

public void setLocation(String location) {
this.location = location;
}

@Column(name = "ReportDate", nullable = false)
public Timestamp getReportDate() {
return this.reportDate;
}

public void setReportDate(Timestamp reportDate) {
this.reportDate = reportDate;
}

@Column(name = "ReportedBy", nullable = false)
public String getReportedBy() {
return this.reportedBy;
}

public void setReportedBy(String reportedBy) {
this.reportedBy = reportedBy;
}

@Column(name = "Status", nullable = false)
public String getStatus() {
return this.status;
}

public void setStatus(String status) {
this.status = status;
}

@Column(name = "Category", nullable = false)
public String getCategory() {
return category;
}

public void setCategory(String category) {
this.category = category;
}

}


All the services are working fine, except for an issue related to two query operations which return data.



The operations getComplaintById and getAllComplaint currently return the entity(s) with all the fields that have values available in database, but with the id field returning as null. I tried structuring the queries in these methods in three ways - using named queries, using native sql and using the find method on entity manager - all of these give the same result.



Just to test, if I try to set the value of id field based on null checking, it is not allowing me, saying the id field has value which is final.



I found same result running the code against both MySQL and Postgres database. Here is code for one of the query method.



public Complaint getComplaintById(Integer id) {     
Complaint cmpl;

//case-1: The NamedQueries as defined in the entity class Complaint --> @NamedQuery(name="cmplById", query="SELECT c FROM Complaint c WHERE c.id = ?1")
//Query query = em.createNamedQuery("cmplById");

//case-2: using NativeQuery
//Query query = em.createNativeQuery("SELECT * FROM COMPLAINT WHERE ID=?1", Complaint.class);

//query.setParameter(1, id);
//cmpl = (Complaint) query.getSingleResult();

//case-3: using find method on entity manager
cmpl = em.find(Complaint.class, id);

System.out.println("id = " + cmpl.getId());//returning null, but get method on all other fields returning their values as expected.

return cmpl;
}


In the log I see that the query statement which OpenJPA is executing includes all other fields but not the id field in the select clause as below.



1720 ramsjpa TRACE ["http-bio-8080"-exec-3] openjpa.jdbc.SQL - executing prepstmnt 14227847 SELECT t0.Category, t0.Description, t0.Location, t0.ReportDate, t0.ReportedBy, t0.Status FROM Complaint t0 WHERE t0.Id = ? [params=?]



I am working with CXF and OpenJPA for the first time, and I may be making a basic mistake, all help appreciated.





No comments:

Post a Comment