2010-07-27 110 views
0

我試圖創建一個以只讀方式包含對象的域對象,但能夠修改它指向的對象。在Servlet環境中使用Hibernate

所以在下面的例子中,我希望Hibernate處理填充Account和Category對象,但我不想永遠更新這些對象。不過,我可能希望更改哪個帳戶或我想要費用指向哪個類別。

換句話說,我可能希望更新費用表上的account_id或category_id,但我絕不希望更改我對Expense對象中包含的Account或Category對象所做更改的帳戶或類別表。

@Entity 
@Table(name = "expense") 
public class Expense { 

    @Id 
    @GeneratedValue 
    private long id; 

    private String name; 

    private BigDecimal amount; 

    @OneToOne 
    @JoinColumn(name = "id", referencedColumnName = "category_id") 
    //From table called category 
    private Category category; 

    @OneToOne 
    @JoinColumn(name = "id", referencedColumnName = "account_id") 
    //From table called account 
    private Account account; 

我完全濫用Hibernate還是它不是正確的工具?我應該使用@SQLUpdate和@SQLInsert定義我自己的SQL嗎?

該應用程序的一般流程是標準的Web應用程序的東西。從數據庫

  • 顯示上的形式
  • 收集由用戶所做的更改

    1. 負載數據
    2. 堅持這些變化

    由於

  • 回答

    1

    這是一個有點從出發的休眠的意圖。對持久對象的更改應該是持久的。如果你不想讓他們的狀態得到保存,不要改變它們!解釋並更好地理解爲什麼你想要這樣的行爲可能會幫助你達成解決方案(或幫助我們幫助你)。

    你擁有的一個選擇是分離/驅逐你不需要的映射對象想要在返回費用對象之前在數據訪問層內進行更改。然後只要沒有級聯,對它們所做的更改就不會被保存。 IMO會導致其他程序員「出乎意料」的行爲。

    另一種選擇是以無會話方式使用hibernate。每次調用都是它自己的原子數據庫操作,所有對象在返回後都會被分離。然後,只有您顯式調用saveOrUpdate的實體纔會保存到數據庫。您可以學習如何配置Hibernate以在Hibernate參考文檔中以這種方式工作,但是我不知道爲什麼您不想效仿某些您正在使用的遺留系統的行爲。

    最後一點需要了解的是,通過調用一個Session,通過調用expense.getCategory()獲得的類別通常是通過調用session.get(Category.class,123)獲得的實際對象。因此,如果在同一個Session中訪問它的兩種方式都可用,那麼如果您嘗試手動管理它,則很容易失去其實體狀態的跟蹤。


    編輯:

    啊,哈!現在它更有意義。

    如果你在做純粹的CRUDy網頁表單屏幕,你沒有太多的擔心。只要您沒有任何級聯,當您合併分離的Expense對象時,CategoryAccount上的更改不會在數據庫中結束。你可以將每個其他領域都清空,只要id仍然存在,你就可以。 (假設你沒有其他的東西像層疊驗證會哭)

    有兩種基本模式可以更好地處理這個問題。

    一個是將Expense對象放在用戶的Web會話中。這樣你就可以完成整個任務,而你的web數據綁定框架只需要將表單實際改變的字段綁定到它上面。原始的CategoryAccount仍然存在(或它們的代理),並且綁定器不需要將它們綁定。當然,缺點是增加服務器端狀態,並且需要清理它。

    二是註冊實際進入數據庫的數據綁定器,並在Web綁定期間獲取映射實體。因此,實際上出現在表單中的所有內容都是映射字段的ID,並且活頁夾將獲取並將完整對象放在那裏。下行可能不需要往返數據庫,但積極的L2緩存可以解決這個問題(假設類別幾乎不會改變,賬號也不會改變)。

    如果您目前正在使用OpenSessionInView/OpenEntityManagerInView模式通過在DAO中創建和部署會話,以基本上無時隙的方式使用hibernate。

    +0

    我在一個servlet環境中工作,所以我的休眠會話只有在我處於應用程序的dao層時纔會持續。該流程是一個標準的網絡應用程序 '從休眠加載數據 - >在窗體上顯示的東西 - >從表單獲取數據 - >將數據加載回數據庫。' 從窗體中取回後,我不一定有Hibernate最初給我的全部對象,只是零散的東西。所以我不想用這些塊覆蓋db中的完整對象。 – Josh 2010-07-28 11:40:32

    +0

    啊哈!回答擴大 – Affe 2010-07-28 17:01:02

    +0

    這正是我正在尋找的。對不起,花了很長時間纔回到它。謝謝! – Josh 2010-08-12 13:18:21

    相關問題