2012-11-20 87 views
0

我有以下類:JPA /休眠 - 與主要作爲一個實體和值作爲集合映射

@Entity 
@Table(name="ripa_request") 
public class ReturningInvoiceRequest implements EntityKey<Long> { 

public enum ReturningInvoiceRequestStatus { 
    /** 
    * This status means that the products for this request are chosen, but not confirmed at all. 
    */ 
    WAITING_TO_SEND("Aguardando envio para o fornecedor"), 

    /** 
    * This status means that the returning request is done but the supplier needs to approve the chosen products. 
    */ 
    WAITING_FOR_ACCEPTANCE("Aguardando aprovação do fornecedor"), 

    /** 
    * This status means that the invoice was generated with the returning request products and the products are dispatched. 
    */ 
    INVOICE_DISPATCHED("Nota Fiscal de devolução emitida"), 

    /** 
    * This status means that something wrong happened on the returning request process. 
    */ 
    INVALID("Requisição inválida"); 

    private String message; 

    private ReturningInvoiceRequestStatus(String message) { 
     this.message = message; 
    } 

    /* (non-Javadoc) 
    * @see java.lang.Enum#toString() 
    */ 
    @Override 
    public String toString() { 
     return message; 
    } 
} 

@Id 
@GeneratedValue 
private Long id; 

/** 
* Mapping for the Products associated to this request with related information: Product Invoice's included with chosen count. 
*/ 
@ElementCollection(targetClass=ProductRequestContext.class) 
@MapKeyJoinColumn(name="product_id") 
@CollectionTable(name="ripa_request_product", [email protected](name="request_id")) 
@Columns(columns={@Column(name="invoice_id"), @Column(name="count")}) 
private Map<Product, Collection<ProductRequestContext>> productCountMap; 

@Temporal(TemporalType.TIMESTAMP) 
private Date date; 

@Enumerated(EnumType.STRING) 
private ReturningInvoiceRequestStatus status; 


public ReturningInvoiceRequest() { 
    this.status = ReturningInvoiceRequestStatus.WAITING_TO_SEND; 
} 

public Long getId() { 
    return id; 
} 

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

public Collection<Product> getProductList() { 
    return this.productCountMap == null ? new ArrayList<Product>() : this.productCountMap.keySet(); 
} 

public void setProductList(Collection<Product> productList) { 
    this.productCountMap = new HashMap<>(); 
    for (Product product : productList) { 
     if (product.getInvoiceList() == null || product.getInvoiceList().isEmpty()) { 
      setStatus(ReturningInvoiceRequestStatus.INVALID); 
      break; 
     } else { 
      List<ProductRequestContext> productContextList = new ArrayList<>(); 
      for (Invoice invoice : product.getInvoiceList()) { 
       productContextList.add(new ProductRequestContext(invoice.getId(), product.getCount(invoice))); 
      } 
      this.productCountMap.put(product, productContextList); 
     } 
    } 
} 

public Date getDate() { 
    return date; 
} 

public void setDate(Date date) { 
    this.date = date; 
} 

public ReturningInvoiceRequestStatus getStatus() { 
    return status; 
} 

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

/** 
* Return the Invoice associated to the informed Product of this request 
* @param product Product business entity 
* @return <code>Invoice</code> Invoice business entity 
*/ 
public Invoice getInvoice(Product product) { 
    for (Product requestProduct : getProductList()) { 
     if (product.equals(requestProduct)) { 
      Collection<ProductRequestContext> contextList = (Collection<ProductRequestContext>) this.productCountMap.get(requestProduct); 
      for (ProductRequestContext context : contextList) { 
       Long invoiceID = context.getRequestInvoiceID(); 
       for (Invoice reqInvoice : requestProduct.getInvoiceList()) { 
        if (invoiceID.equals(reqInvoice.getId())) { 
         return reqInvoice; 
        } 
       } 
      } 
     } 
    } 
    return null; 
} 

/** 
* Return the quantity of the informed Product selected for this request. 
* @param product Product business entity 
* @return 
*/ 
public Integer getCount(Product product) { 
    for (Product requestProduct : getProductList()) { 
     if (product.equals(requestProduct)) { 
      Collection<ProductRequestContext> contextList = (Collection<ProductRequestContext>) this.productCountMap.get(requestProduct); 
      for (ProductRequestContext context : contextList) { 
       Long invoiceID = context.getRequestInvoiceID(); 
       for (Invoice reqInvoice : requestProduct.getInvoiceList()) { 
        if (invoiceID.equals(reqInvoice.getId())) { 
         return context.getRequestCount(); 
        } 
       } 
      } 
     } 
    } 
    return null; 
}  


/* (non-Javadoc) 
* @see br.com.mls.eanf.entity.ifc.EntityKey#getKey() 
*/ 
public Long getKey() { 
    return id; 
} 

/* (non-Javadoc) 
* @see java.lang.Object#hashCode() 
*/ 
@Override 
public int hashCode() { 
    final int prime = 31; 
    int result = 1; 
    result = prime * result + ((id == null) ? 0 : id.hashCode()); 
    return result; 
} 

/* (non-Javadoc) 
* @see java.lang.Object#equals(java.lang.Object) 
*/ 
@Override 
public boolean equals(Object obj) { 
    if (this == obj) 
     return true; 
    if (obj == null) 
     return false; 
    if (getClass() != obj.getClass()) 
     return false; 
    ReturningInvoiceRequest other = (ReturningInvoiceRequest) obj; 
    if (id == null) { 
     if (other.id != null) 
      return false; 
    } else if (!id.equals(other.id)) 
     return false; 
    return true; 
} 

/* (non-Javadoc) 
* @see java.lang.Object#toString() 
*/ 
@Override 
public String toString() { 
    return this.id == null ? super.toString() : this.id.toString(); 
} 



@Embeddable 
public static class ProductRequestContext { 
    /** 
    * Sequence identifier for the Invoice registry on this context. 
    */ 
    @Column(name="invoice_id") 
    private long requestInvoiceID; 

    @Column(name="count") 
    private int requestCount; 

    public ProductRequestContext() { 
    } 

    ProductRequestContext(Long invoiceID, Integer count) { 
     this.requestInvoiceID = invoiceID; 
     this.requestCount = count; 
    } 

    public Long getRequestInvoiceID() { 
     return requestInvoiceID; 
    } 

    public void setRequestInvoiceID(Long invoiceID) { 
     this.requestInvoiceID = invoiceID; 
    } 

    public int getRequestCount() { 
     return requestCount; 
    } 

    public void setRequestCount(int count) { 
     this.requestCount = count; 
    } 
} 

}

與元素的集合的映射關係時發生該問題,在此期間在ReturningInvoiceRequest實體的插入(由EntityManager的的persit法):

javax.persistence.PersistenceException: org.hibernate.PropertyAccessException: could not get a field value by reflection getter of br.com.mls.ripa.domain.model.product.ReturningInvoiceRequest$ProductRequestContext.requestCount 

我的研究,我發現關於休眠不支持收藏的一些信息在地圖的值,也是一個MultiMap的方法http://blog.xebia.com/2007/10/05/mapping-multimaps-with-hibernate/,但我不知道它是否會解決我的問題

我也嘗試使用Google Collections中的Multimap類來取消Collection值,也沒有因爲它沒有擴展java.util.Map,這是hibernate理解的,而且apache-collections MultiMap不支持泛型,這對於Hibernate映射是必需的

我使用的是Hibernate 3.6 .9,但在版本4.1.8上,錯誤仍然存​​在。

感謝

回答

0

我找到的解決方案是使用ProductRequestContext列表:

@ElementCollection 
@CollectionTable(name="ripa_request_product", [email protected](name="request_id")) 
@Columns(columns={@Column(name="product_id"), @Column(name="invoice_id"), @Column(name="count")}) 
private List<ProductRequestContext> productCountList