2012-04-18 45 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();