2012-04-18 27 views
0

我正在使用Apache CXF(版本2.5.2)实现在数据库表上添加,更新,删除,查询单个记录和列表记录的REST服务。我在持久层中使用OpenJPA(版本2.2.0)。OpenJPA - 实例的id字段在查询中返回空值

作为一个例子,我有一个名为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; 
    } 

} 

所有服务都正常工作,除了与两个查询操作有关的问题返回数据。

的操作getComplaintByIdgetAllComplaint目前正与那些在数据库中可用值的所有字段,但与id字段返回为空返回实体(或多个)。我尝试用三种方法构造这些方法中的查询 - 使用命名查询,使用本机sql并在实体管理器上使用find方法 - 所有这些都给出了相同的结果。

只是为了测试,如果我尝试根据空检查设置id字段的值,它不允许我说id字段具有最终的值。

我发现对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的生物8080” -exec-3] openjpa.jdbc.SQL - 执行prepstmnt 14227847 SELECT t0.Category,t0.Description,t0.Location,t0.ReportDate,t0.ReportedBy, t0.Status从投诉t0 WHERE t0.Id =? [params =?]

我第一次和CXF和OpenJPA一起工作,我可能会犯一个基本错误,所有的帮助表示赞赏。

+0

您不包括实体类的实际来源。请将其添加到您的问题。如果此实体中的“id”字段有任何机会标记为最终的?编辑代码时不要忘记包含'getId()'的定义。 – Perception 2012-04-18 04:25:56

+0

@Perception,感谢您的快速响应,我添加了实体类,id字段未标记为final。 – user1340182 2012-04-18 08:40:34

+0

你如何增强你的实体? – Rick 2013-04-24 19:08:26

回答

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();