2011-05-30 90 views
7

我正在增強一箇舊的Spring/Hibernate應用程序,我卡住了。我有一個讀取文件長度超過3000行的方法,每行都有一條記錄,必須與數據庫上的某個記錄進行比較,然後必須將一個寄存器添加到數據庫(多到多個表)。休眠掛起或拋出懶惰初始化沒有會話或會話被關閉

表和關係

分公司許多產品產品許多分支

產品很多產品類別許多產品

還有更多的是在那裏和好的工作表。

表/我創建的對象是分公司,產品,BranchToProduct

產品有一套BranchToProduct對象,其中有3場

我需要BranchToProduct對象添加到集產品,用3個領域,從信息,我從文件中的每一行得到填補。

我添加一個簡單的線和所述應用程序拋出:

產物= productDAO.findByModel(stringModel);

無法懶洋洋地初始化集合 作用: com.bamboo.catW3.domain.Product.products, 沒有會話或會話關閉

如果我去Hibernate映射(HBM文件)並設置關係product_to_products lazy = false,行單獨運行,但如果我試圖把它放在文件循環中,應用程序總是在正在處理的第18行掛起,無論我使用哪個文件或順序內容,控制檯停止工作,不得不關閉java查殺進程。無論哪種方式,在調試中,我得到很多HQL的簡單查找,13行HQL,直到我得到我的錯誤,當lazy = true,並且當我使用lazy = false並且把它放在很多行時週期。

我想我應該試着用lazy = true來解決這個問題。

這種情況讓我懷疑:

1.-當懶惰=真。我怎麼能不能運行這個命令的這一行的單行,但它在類的其他方法上工作正常?

的方式,這是一種稱爲CatalogFacade類,它實現其他clasess的方法:(CategoryFacade,ContainerFacade,ProductFacade,ProductOptionFacade,ProductStatusFacade,UserFacade,EmailFacade,FileFacade,BranchOfficeFacade)

這是代碼
productDao.find():

public Product find(Integer id) throws DataAccessException { 

     Product product= (Product) super.find(Product.class, id); 


     if(product!=null){ 
      product.setProductAttributes(new TreeSet<ProductAttribute>(product.getProductAttributes())); 

      for (Product ptp : product.getProducts()){ 
       ptp.setProductAttributes(new TreeSet<ProductAttribute>(ptp.getProductAttributes())); 

      } 

     } 

異常被拋出了就在這條線,在最後爲:

pptp.setProductAttributes(new TreeSet<ProductAttribute>(ptp.getProductAttributes())) 

在Intelij的調試器,我可以看到從查詢錯誤地形成的物體:){[email protected]}unable

product.getProducts(=計算表達式方法扔「org.hibernate作爲.LazyInitializationException'異常。

如何過其他屬性都OK。該產品甚至沒有其他產品在數據庫中。

UPDATE

挖的情況越深,

product.find內(INT)

在行之前,我得到的異常,我們可以看到product.products數組有錯誤的調試,而不是您可以看到lazyInitialitationException的值。 如何從,如果我從另一個方法調用它,該數組是查找。所以它不能在它內部即使該方法只接收一個整數。

此外,我們發現,這已經沿着應用的全生命週期的發生,有時工作人員複製的方法一樣,但更改它設置爲null這個損壞的陣列。所以我100%肯定這個應用程序正在消耗更多的資源。

它有意見Flex和JSTL中後視圖,其中創造,並根據誰在調用方法時,例外在同一方法不同的方式拋出。

添加更多信息。這是produt.find如何在AbstractDAOImpl實施:

public final Object find(Class clazz, Integer id) throws DataAccessException{ 

     return getHibernateTemplate().get(clazz,id); 
} 

,這是我的事務管理器的配置,在由彈指第一個答案描述沒有工作的標註方法:

<bean id="catalogFacade" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> 
    <property name="transactionManager"> 
     <ref local="transactionManager"/> 
    </property> 
    <property name="target"> 
     <ref local="catalogFacadeTarget"/> 
    </property> 
    <property name="transactionAttributes"> 
     <props> 
      <prop key="add*">PROPAGATION_REQUIRED</prop> 
      <prop key="save*">PROPAGATION_REQUIRED</prop> 
      <prop key="update*">PROPAGATION_REQUIRED</prop> 
      <prop key="delete*">PROPAGATION_REQUIRED</prop> 
      <prop key="remove*">PROPAGATION_REQUIRED</prop> 
      <prop key="get*">PROPAGATION_SUPPORTS,readOnly</prop> 
      <prop key="find*">PROPAGATION_SUPPORTS,readOnly</prop> 
      <prop key="contains*">PROPAGATION_SUPPORTS,readOnly</prop> 
      <prop key="login*">PROPAGATION_SUPPORTS,readOnly</prop> 
     </props> 
    </property> 
</bean> 

回答

0

我以前遇到同樣的問題,並通過使用不同的hibernate方法修復它。我用

getHibernateTemplate().loadAll(class) 

爲讓所有的東西,

getHibernateTemplate().get(class, id) 

找到一個單一的東西。這兩個我用沒有問題。我發現.find()給我那個會話被關閉的錯誤。

我還沒有真正考慮過這是爲什麼。

我可以使用另一種方法想拋開唯一的其他選擇是自己打開和關閉會話,但我相信你不想這樣做。

+0

其實這就是如何在程序已經在做了,看到更新代碼 – Ernest 2011-05-31 23:20:38

19

,因爲你的會話,你獲得產品的成員變量之前被關閉你得到一個延遲初始化例外。當執行以下行時:

Product product= (Product) super.find(Product.class, id) 

Hibernate打開一個會話,檢索您正在查找的內容,然後關閉會話。任何lazy = true的字段都是而不是此時檢索;相反,這些字段由代理填充。當您嘗試檢索代理對象的實際值時,它將嘗試使用活動會話回到數據庫以檢索數據。如果沒有會話可以找到,你會看到你看到的異常。設置lazy = true具有優勢,因爲它可以防止整個對象圖形立即加載;嵌套的對象是獨自留下,直到你特意請求它們。

有兩種常用的技術來處理你的問題。您已經確定的第一個,即設置lazy = false。如果產品始終具有產品屬性,並且您通常使用產品並將其屬性組合在一起,則這很好。如果您經常只需要沒有其屬性的Product對象,就會創建不必要的數據庫負載。

第二種技術是標記使用Spring註釋作爲事務的方法。

@Transactional 
public Product find(Integer id) throws DataAccessException { 

} 

的幾個注意事項:

  1. 您需要交易一些額外 配置 工作(@Transactional註釋 是不夠的)。有關 的更多信息,請參閱here
  2. 最佳實踐規定您在服務層中註釋方法,而不是數據訪問層。
+0

你好彈指,我都試過了2種方法你提到。第一個在第18次調用數據庫之後掛起應用程序,註解不起作用,但仍然非常奇怪,因爲該方法適用於現在調用此方法的同一類的其他方法上的不同調用。我要添加我的方面配置,看看它是否有幫助。我還能檢查什麼? – Ernest 2011-05-31 23:16:07

+0

第18次電話會議後,你的意思是什麼?另外,您是否通過CatalogFacade或DAO中的產品屬性調用了循環? – Fil 2011-06-01 12:33:13

+0

至於你在問題本身的意見,通過調試器檢查延遲加載字段將觸發延遲初始化應用程序本身相同的方式;檢索嘗試是在一個tranasaction之外進行的。在產品屬性上設置lazy = false是否適合您? – Fil 2011-06-01 12:36:30

0

替換GET方法加載方法..

我做更多的研究負載方法並沒有真正從數據庫中加載對象之後發現了。相反,它會自動返回一個代理對象。負載假設該對象已經從數據庫「獲得」並處於緩存中。

只要用得到的,而不是負擔,如果你想確保你打的數據庫,並確保你知道這2種方法之間的差異。

來源:this spring forum comment

我親自測試這一點,它是正確的,負載方法不檢索的數據庫中的所有所需的數據。使用得到解決我的問題。

相關問題