2012-01-17 59 views
0

在我的一個數據模型,其中有屬性映射到枚舉很多這樣的實體:JPA:地圖無效的數據庫值來枚舉

@Enumerated(EnumType.STRING) 
private MySpecialEnum enumValue; 

MySpecialEnum定義了一些固定值。映射工作正常,如果數據庫爲列保留NULL值,我也在enumValue屬性中獲得NULL。 問題是,我的後端模塊(我沒有影響)使用CHAR列中的空格來標識沒有設置值。所以我得到一個IllegalArgumentException而不是NULL值。

所以我的問題是:是否有JPA事件,我可以在映射到枚舉屬性之前更改從數據庫中讀取的值? 對於寫入訪問,有@PrePersist,我可以將空值更改爲空格。我知道有@ PostLoad事件,但這是在映射後處理的。

順便說一句:我使用OpenJpa在WebSphere Application Server中發佈。

回答

0

您可以映射枚舉型字段作爲@Transient(它不會被持久化),另一場直接映射爲字符串,在@PostLoad同步它們:

@Transient 
private MyEnum fieldProxy; 

private String fieldDB; 

@PostLoad 
public void postLoad() { 
    if (" ".equals(fieldDB)) 
     fieldProxy = null; 
    else 
     fieldProxy = MyEnum.valueOf(fieldDB); 
} 

使用get/setFieldProxy()在Java代碼中。

至於同步的另一種方式,我會做一個setter,而不是​​,因爲對@Transient字段的更改可能不會將實體標記爲已修改,並且更新操作可能不會被觸發(我是不知道這個問題):

public void setFieldProxy(MyEnum value) { 
    fieldProxy = value; 
    if (fieldProxy == null) 
     fieldDB = " "; 
    else 
     fieldDB = value.name(); 
} 
+0

非常感謝您的回答。但我正在尋找更通用的解決方案。對於你建議的方式,我必須爲每個枚舉字段編寫這段代碼,但是我必須爲我的數據模型中的所有枚舉字段實現它。順便說一句,我喜歡讓我的實體簡單和愚蠢。 – 2012-01-21 16:52:15

0

OpenJPA中提供@Externalizer@Factory來處理 「特殊」 的數據庫值。

看到這個:http://ci.apache.org/projects/openjpa/2.0.x/manual/manual.html#ref_guide_pc_extern_values

你可能最終得到這樣的:沒有測試...

@Factory("MyClass.mySpecialEnumFactory") 
private MySpecialEnum special; 

... 

public static MySpecialEnum mySpecialEnumFactory(String external) { 
    if(StringUtils.isBlank(external) return null; // or why not MySpecialEnum.NONE; 
    return MySpecialEnum.valueOf(external); 
}