2012-07-05 26 views
2

我正在使用Seam 2.2.2,JSF Mojarra 1.2_13-b01-FCS,JBoss 5.1.0 Server。將JSF貨幣映射爲數據庫上的NUMBER

我有一個Oracle表,其中有三列指定爲NUMBER類型。生成的hibernate映射已將實體類中的那些列映射爲java.math.BigDecimal。這些是貨幣值,BigDecimal似乎是在Java中存儲和計算這些值的首選方式。

我想使用數字轉換器在屏幕上使用貨幣在h:inputText和h:outputText中的值。正常工作,直到我嘗試更新這些值中的一個,當java的拋出異常:

EquipItemEdit.xhtml值=「#{equipItemHome.instance.cost}」:java.lang.IllegalArgumentException異常:參數類型不匹配

我的實體映射,如:數據庫

CREATE TABLE EQUIP_ITEM 
(
    EQUIP_ID  NUMBER, 
    COUNTER  NUMBER, 
    ITEM   VARCHAR2(6 BYTE), 
    ACQADC  VARCHAR2(1 BYTE), 
    COG   VARCHAR2(2 BYTE), 
    COST   NUMBER, 
    NOMENC  VARCHAR2(40 BYTE), 
    QUA_AUTH  NUMBER, 
    ... 
) 

而光場是如何在JSP映射

@Entity 
@Table(name = "EQUIP_ITEM") 
public class EquipItem implements java.io.Serializable { 
    ... 

    private BigDecimal cost; 
    ... 

     @Column(name = "COST", precision = 22, scale = 0) 
    public BigDecimal getCost() { 
     return this.cost; 
    } 

    public void setCost(BigDecimal cost) { 
     this.cost = cost; 
    } 

    ... 
} 

表定義:

... 
<h:inputText id="cost" 
styleClass="value" 
      value="#{equipItemHome.instance.cost}" 
      size="15"> 
    <f:convertNumber type="currency" currencySymbol="$" locale="en_US"/>           
</h:inputText> 
... 

任何建議,或有人可以指點我正確的方式來處理這種數據類型?


現在爲了讓事情能夠正常工作,我寫了自己的轉換器。還沒有做過多的測試,並希望有人能告訴我如何讓JSF內置轉換器爲此工作。

import java.io.Serializable; 
import java.math.BigDecimal; 
import java.text.NumberFormat; 
import java.text.ParseException; 
import java.util.Locale; 

import javax.faces.component.UIComponent; 
import javax.faces.context.FacesContext; 

import org.jboss.seam.annotations.Name; 
import org.jboss.seam.annotations.intercept.BypassInterceptors; 

@Name("usDollarsConverter") 
@BypassInterceptors 
@org.jboss.seam.annotations.faces.Converter 
public class UsDollarsConverter implements javax.faces.convert.Converter, Serializable { 

    public Object getAsObject(FacesContext context, UIComponent component, String  string) { 
     if(string == null) { 
      return null; 
     }  

     try { 
      NumberFormat nf = NumberFormat.getCurrencyInstance(Locale.US);   
      nf.setMinimumFractionDigits(2); 
      nf.setMaximumFractionDigits(2);   
      Object value = nf.parse(string); 
      if(value instanceof Double) { 
       value = new BigDecimal((Double)value); 
      } else if(value instanceof Long) { 
       value = new BigDecimal((Long) value); 
      } 
      return value; 
     } catch (ParseException e) { 
      return null; 
     }   

    } 

    public String getAsString(FacesContext context, UIComponent component, Object value) { 
     if(value == null) { 
      return null; 
     } 

     if(value instanceof Double) { 
      value = new BigDecimal((Double)value); 
     } else if(value instanceof Long) { 
      value = new BigDecimal((Long) value); 
     } 



     if(value instanceof BigDecimal) { 
      NumberFormat nf = NumberFormat.getCurrencyInstance(Locale.US);   
      nf.setMinimumFractionDigits(2); 
      nf.setMaximumFractionDigits(2);   
      return nf.format(((BigDecimal)value).doubleValue());    
     } 

     throw new java.lang.IllegalArgumentException("UsDollarsConverter requires a type java.math.BigDecimal, will not work with " +  value.getClass().getCanonicalName()); 
    } 


} 

回答

1

儘管它的名字,<f:convertNumber/>不會轉換BigDecimal ...如果你檢查的Javadoc javax.faces.convert.NumberConverter,它告訴它會產生無論是Long(爲整數號)或Double。這是因爲,要使用NumberFormat解析BigDecimals,您需要設置一個標記setParseBigDecimal(true),否則NumberFormat對象只會生成雙精度。

JSF確實提供了BigDecimals的(恰當地命名爲javax.faces.BigDecimal)獨立的轉換器,而不是<f:convertNumber/>使用:

<f:converter converterId="javax.faces.BigDecimal" />

而轉化工作。但該轉換器不如<f:convertNumber/>靈活,您不能設置模式或使用不同的語言環境等。因此,大多數人只是編寫自己的轉換器實現。