2013-04-18 21 views
1

我有一個@Embeddable類,它使用屬性訪問來包裝另一個對象,該對象不能由JPA通過字段訪問直接映射。它看起來像這樣:JPA EclipseLink Weaver在其setter中生成對porperty getter的調用 - > NullPointerException

@Embeddable 
@Access(AccessType.PROPERTY) 
public class MyWrapper { 

    @NotNull 
    @Transient 
    private WrappedType wrappedField; 

    protected MyWrapper() { 
    } 

    public MyWrapper(WrappedType wrappedField) { 
     this.wrappedField = wrappedField; 
    } 

    @Transient 
    public WrappedType getWrappedField() { 
     return wrappedField; 
    } 

    public void setWrappedField(WrappedType wrappedField) { 
     this.wrappedField = wrappedField; 
    } 

    @Column(name = "wrappedTypeColumn") 
    protected String getJPARepresentation() { 
     return wrappedField.toString(); 
    } 

    protected void setJPARepresentation(String jpaRepresentation) { 
     wrappedField = new WrappedType(jpaRepresentation); 
    } 
} 

堅持用MyWrapper領域的@Entity工作正常。但是當我執行查詢從數據庫加載實體時,我得到一個NullPointerException。堆棧跟蹤和一些調試顯示Eclipselink通過調用其默認構造函數創建一個新的MyWrapper實例,然後調用setJPARepresentation()方法(如預期的那樣)。

但是現在意外發生了:堆棧跟蹤顯示是從setter中調用的,當然返回wrappedField.toString()執行時會導致NullPointerException

java.lang.NullPointerException 
    at MyWrapper.getJPARepresentation(MyWrapper.java:27) 
    at MyWrapper.setJPARepresentation(MyWrapper.java) 
    ... 109 more 

事實是,有明顯的代碼到吸氣劑沒有呼叫和棧跟蹤示出了從其中的setter稱爲吸氣指示沒有行號。所以我的結論是,Eclipselink的字節碼編織器產生了對getter的調用。

建立一個解決方法很容易,但我的問題是:爲什麼Eclipselink會這樣做?

PS:我使用的EclipseLink 2.3.2.v20111125-r10461在GlassFish應用服務器版本3.1.2(建立23)

回答

0

啓用編織(Glassfish上默認值),將的EclipseLink編織碼成用於屬性get/set方法,

  • 變化跟蹤
  • 取組(局部對象)
  • 懶惰(關係)

對於更改跟蹤支持,將編制set方法來檢查新值是否與舊值不同,因此它必須調用get方法來獲取舊值。

現在,這仍然是奇怪的,因爲你正在建立一個新的對象,我不希望更改監聽器被設置,所以會期望變更跟蹤檢查被繞過。您可以反編譯代碼以確切地查看生成的內容。

最簡單的解決方法是在get方法中放入一個空檢查,這對您的代碼來說可能是最好的。你也可以切換到字段訪問,這在get/set方法中不會產生副作用。您也可以使用Converter來處理轉換,而不是在get/set方法中進行轉換。

+0

無法使用字段訪問,因爲JPA沒有本地支持來映射'MyWrapper',我不能使用轉換器我不允許使用提供程序依賴的機制,因爲代碼必須與OpenJPA一起運行。 – 2013-04-18 14:16:51

相關問題