我正在使用Apache CXF(版本2.5.2)来实现REST服务,这些服务可以添加,更新,删除,查询数据库表上的单个记录和记录列表。我在持久层中使用OpenJPA(版本2.2.0)。
作为一个例子,我有一个名为Complaint的表,映射到同名的实体类。投诉实体与此类似:
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;
}
}
除了与返回数据的两个查询操作相关的问题外,所有服务都正常工作。
操作getComplaintById
和getAllComplaint
当前返回的实体包含数据库中可用值的所有字段 ,但id字段返回为null 即可。我尝试以三种方式构建这些方法中的查询 - 使用命名查询,使用本机sql并在实体管理器上使用find方法 - 所有这些都给出了相同的结果。
只是为了测试,如果我尝试根据空值检查设置id字段的值,它不允许我,说id字段的值是final。
我发现同样的结果是针对MySQL和Postgres数据库运行代码。以下是查询方法之一的代码。
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;
}
在日志中我看到OpenJPA正在执行的查询语句包括所有其他字段,但不包括select子句中的id字段,如下所示。
1720 ramsjpa TRACE [“http-bio-8080”-exec-3] openjpa.jdbc.SQL - 执行prepstmnt 14227847 SELECT t0.Category,t0.Description,t0.Location,t0.ReportDate,t0.ReportedBy,t0 .Status FROM Complaint t0 WHERE t0.Id =? [PARAMS =?]
我第一次与CXF和OpenJPA合作,我可能会犯一个基本的错误,所有帮助都很受欢迎。
答案 0 :(得分:0)
您是否可以在将其插入数据库后立即调用 getComplaintById ?如果是这样,那么您的问题可能与您的Id字段使用 GenerationType.IDENTITY 有关。使用GenerationType.IDENTITY,由于在插入行之前数据库未分配id,因此在提交之后或刷新调用之后,无法在对象中获取id。 (参考:http://en.wikibooks.org/wiki/Java_Persistence/Identity_and_Sequencing#Identity_sequencing)
所以我认为在尝试通过Id找到您的投诉之前,您需要执行以下操作:
Complaint complaint = new Complaint();
// Fill in your complaint fields...
em.persist(complaint);
em.flush();
em.getTransaction().commit();