2012-04-18 3 views
0

Apache CXF (버전 2.5.2)를 사용하여 데이터베이스 테이블에서 단일 레코드 및 레코드 목록을 추가, 업데이트, 삭제, 수행하는 REST 서비스를 구현하고 있습니다. 지속성 레이어에서 OpenJPA (버전 2.2.0)를 사용하고 있습니다.OpenJPA - 인스턴스의 id 필드가 쿼리에서 null을 반환합니다.

예를 들어, 같은 이름의 엔티티 클래스에 매핑 된 불만이라는 테이블이 있습니다. 불만 법인이 유사합니다

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 필드가 null로를 반환으로 엔티티 (들)을 반환합니다. 세 가지 방법으로 쿼리를 구조화하려고했습니다. 네이티브 SQL을 사용하고 엔터티 관리자에서 find 메서드를 사용하여 명명 된 쿼리를 사용하여 이러한 모든 결과가 동일한 결과를 제공합니다.

null 검사를 기반으로 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-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 어디에서 t0.Id =? [params =?]

저는 CXF 및 OpenJPA에서 처음으로 작업 중이며, 기본적인 실수를 저질렀습니다. 모든 도움을 주실 수 있습니다.

+0

당신은 당신의 엔티티 클래스의 실제 소스를 포함하지 않았다. 귀하의 질문에 그것을 추가하십시오. 이 엔티티의'id' 필드가 임의로 final로 표시되면? – Perception

+0

@Perception에 코드를 편집 할 때 getId()에 대한 정의를 포함하는 것을 잊지 마십시오. 빠른 응답을 주셔서 감사합니다. 엔티티 클래스를 추가했으며 id 필드는 final로 표시되지 않았습니다. – user1340182

+0

어떻게 귀하의 법인을 강화하고 있습니까? – Rick

답변

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(); 
관련 문제