2010-05-20 39 views
5

所以這裏是我的難題。我正在編寫一個需要在我們的應用程序的舊版本上工作的工具。我有應用程序的代碼,但不能更改任何類。爲了從我們的數據庫中提取信息,我有一個由Hibernate填充的DTO。它爲我們的應用程序的版本1.0使用了一個數據對象,巧妙地命名爲DataObject。以下是DTO課程。Java類的特定版本實現模式

public class MyDTO { 
    private MyWrapperClass wrapper; 

    public MyDTO(DataObject data) { 
     wrapper = new MyWrapperClass(data); 
    } 
} 

的DTO通過一個Hibernate查詢實例如下:

select new com.foo.bar.MyDTO(t1.data) from mytable t1 

現在,需要對數據對象的頂部一點的邏輯,所以我提出的包裝類它。請注意,DTO存儲包裝類的實例,而不是原始數據對象。

public class MyWrapperClass { 

    private DataObject data; 

    public MyWrapperClass(DataObject data) { 
     this.data = data; 
    } 

    public String doSomethingImportant() { ... version-specific logic ... } 
} 

這很好,直到我需要在我們的應用程序的2.0版工作。現在DataObject在兩個版本中非常相似,但不一樣。這導致了MyWrapperClass的不同子類,它們實現了它們自己的特定於版本的doSomethingImportant()。仍然沒有問題。但是,myDTO如何實例化適當的版本特定的MyWrapperClass? Hibernate反過來實例化MyDTO,所以它不像我可以在@Autowire中依賴Spring。

我很想重用MyDTO(和我的許多其他的DTO的),該工具的兩個版本,而無需複製類。不要重複自己,以及所有這一切。我敢肯定,我錯過了一個非常簡單的模式,可以幫助解決這個問題。有什麼建議麼?

回答

0

我的同事和我嘗試了很多選擇。我們決定使用Hibernate的記錄不完整的ResultTransformer接口(實際上,Hibernate,缺乏文檔是可恥的)。儘管使用Transformer迫使我們在我們的MyDTO構造函數中手動解析Object []數組,但這是一個值得考慮的折衷。

在ResultTransformer中,我們通過Spring注入了特定於版本的WrapperFactory。我們更改了查詢以允許ResultTransformer實例化MyDTO,並且瞧!問題解決了。下面是我們修改後的查詢和DTO類:

"select t1.data from mytable t1" 

public class MyDTO<T> { 
    private MyWrapperClass wrapper; 

    public MyDTO(Object[] fields, WrapperFactory<T> wrapperFactory) { 
     T data = (T) fields[0];   
     wrapper = wrapperFactory.newWrapper(data); 
    } 
} 

按我的意見,紀堯姆,攔截並沒有如願工作。推測是因爲MyDTO不是一個持久的類。

我們還嘗試讓DTO直接通過單例類訪問ApplicationContext,並從那裏獲取WrapperFactory。雖然這有效,但它可預測地取消了我們的單元測試,並且我們放棄了這種方法。

1

您可以使用Hibernate的Interceptor的實施instantiate(String entityName, EntityMode entityMode, Serializable id)

在該方法中,您可以將MyWrapperClass傳遞給您的數據對象。根據您的應用程序的版本,包裝將有所不同。攔截器可以在會話級別或會話工廠級別設置。

+0

這對我們不起作用,大概是因爲MyDTO不是持久性類。觸發的唯一攔截器方法是afterTransactionBegin(),onPrepareStatement(),beforeTransactionCompletion()和afterTransactionCompletion()。這些都沒有給我們正確的窗口來操縱數據。 但是,當我們最終找到Hibernate的ResultTransformer接口時,您確實設置了正確的路徑。謝謝! – 2010-05-28 15:44:08

+0

酷,很高興我可以幫助一點:) – Guillaume 2010-05-28 18:13:59