2010-06-04 110 views
2

我知道這已經被討論了很多次。我不明白這項工作或我的錯誤在哪裏。
我認爲給你一個簡化的例子是告訴你我想要做什麼以及我正在採取什麼假設的最好方法...Spring/Hibernate需要的幫助懶惰加載

我有一個帶名稱的產品類。該名稱是一個懶惰的String屬性。

吾道:

public abstract class HibernateProductDAO extends HibernateDaoSupport implements ProductDAO 
{ 
    public List getAll() 
    { 
     return this.getHibernateTemplate().find("from " + this.getDomainClass().getSimpleName()); 
    } 
} 

我的服務接口:

public interface ProductService { 
    //This methods are Transactional, but same exception error is thrown if there weren't 
    @Transactional 
    public Product getProduct(); 
    @Transactional 
    public String getName(Product tp); 
} 

我的服務實現:

public class ProductServiceImpl implements ProductService { 
    private ProductDAO productDAO; 
    public Product getProduct() { 
     List ps = this.productDAO.getAll(); 
     return (Product) ps.get(0); 
    } 
    public String getName(Product p){ 
     return p.getName(); 
    } 
} 

我的主類:

public class Main { 
    private ProductService productService; 
    public static void main(String[] args) { 
     Main main= new Main();   
     main.productService= (ProductService)(new ClassPathXmlApplicationContext("applicationContext.xml")).getBean("productProxy"); 
     //load the product without the name 
     Product p = main.productService.getProduct(); 
     //load the lazy name 
     System.out.println(main.productService.getName(p)); //EXCEPTION IS THROWN IN THIS LINE 
    } 
    public void setProductService(ProductService productService) { 
     this.productService= productService; 
    } 

    public ProductService getProductService() { 
     return productService; 
    } 

我的applicationContext.xml:

<?xml version="1.0" encoding="UTF-8" ?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:util="http://www.springframework.org/schema/util" 
    xmlns:jee="http://www.springframework.org/schema/jee" 
    xmlns:lang="http://www.springframework.org/schema/lang" 
    xmlns:aop="http://www.springframework.org/schema/aop" 
    xmlns:tx="http://www.springframework.org/schema/tx" 
    xmlns:sca="http://xmlns.oracle.com/weblogic/weblogic-sca"> 

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
     <property name="driverClassName"><value>oracle.jdbc.driver.OracleDriver</value></property> 
     <property name="url"><value>jdbc:oracle:thin:@${hostname}:${port}:${schema}</value></property> 
     <property name="username"><value>${username}</value></property> 
     <property name="password"><value>${password}</value></property> 
    </bean> 

    <!-- Hibernate SessionFactory --> 
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> 
     <property name="dataSource"><ref local="dataSource"/></property> 
     <property name="configLocation"><value>hibernate.cfg.xml</value></property> 
     <property name="configurationClass"><value>org.hibernate.cfg.AnnotationConfiguration</value></property> 
    </bean> 

    <!-- Transaction manager for a single Hibernate SessionFactory (alternative to JTA) --> 
    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> 
     <property name="sessionFactory"><ref local="sessionFactory"/></property> 
    </bean> 

    <bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate"> 
     <property name="sessionFactory"><ref bean="sessionFactory"/></property> 
     <property name="allowCreate" value="true"/> 
    </bean> 
    <bean id="productDAO" class="product.model.data.ProductDAO" > 
     <property name="sessionFactory" ref="sessionFactory"/> 
</bean> 
    <bean id="hibernateInterceptor" 
     class="org.springframework.orm.hibernate3.HibernateInterceptor"> 
     <property name="sessionFactory"> 
      <ref bean="sessionFactory"/> 
     </property> 
    </bean> 
    <bean id="productService" 
     class="product.services.ProductServiceImpl"> 
     <property name="productDAO"> 
      <ref bean="ProductDAO"/> 
     </property> 
    </bean> 
    <bean id="productProxy" 
     class="org.springframework.aop.framework.ProxyFactoryBean"> 
     <property name="target"> 
      <ref bean="productService"/> 
     </property> 
     <property name="proxyInterfaces"> 
      <value>product.services.ProductService</value> 
     </property> 
     <property name="interceptorNames"> 
      <list> 
       <value>hibernateInterceptor</value> 
      </list> 
     </property> 
    </bean> 
</beans> 

異常片段:

11:59:57,775 [main] DEBUG org.springframework.orm.hibernate3.SessionFactoryUtils - Opening Hibernate Session 
11:59:57,775 [main] DEBUG org.hibernate.impl.SessionImpl - opened session at timestamp: 12749723977 
11:59:57,777 [main] ERROR org.hibernate.LazyInitializationException - could not initialize proxy - no Session 
org.hibernate.LazyInitializationException: could not initialize proxy - no Session 
    at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:108) 
    at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:150) 
    at org.hibernate.proxy.pojo.cglib.CGLIBLazyInitializer.invoke(CGLIBLazyInitializer.java:150) 

我說得對,如果我假設器HibernateInterceptor保持不同的呼叫中Hibernate的Session打開?如果我是這樣的話,爲什麼會在加載產品對象後關閉會話?

我在某處讀了我也可以使用OpenSessionInViewInterceptor,但我無法使它工作。你如何將這個攔截器添加到這個小例子中?

有沒有任何代碼錯誤或錯誤理解如何工作?

你知道任何簡單的示例代碼,我可以下載來檢查它是如何工作的嗎?

由於提前, Neuquino

回答

6

的問題是,器HibernateInterceptor從ProductService getProduct()

返回從API DOCs後關閉會話:

這個攔截之前綁定一個新的Hibernate Session的線程方法調用,在任何方法結果的情況下關閉並刪除它。如果已經存在預先綁定的會話(例如來自HibernateTransactionManager或者周圍的Hibernate截獲的方法),那麼攔截器就會參與其中。

並打開一個新的電話ProductService.getProductName()。新創建的會話不知道您在前一個會話中從數據庫中獲取的產品實體。

你有各種可能性,以解決此問題:

1)添加哪些熱切加載名稱的方法,並在特定情況下使用它,這是obviuos;)

2。),你可以在ProductService.getProductName()

3.調用Product.getName()之前重新將實體使用Session.update(myProductEntity)活動會話),你可以用它全部在包裝的方法調用ProductService.getProduct()ProductService.getProductName()參與事務。見Transaction Propagation

4.)在Web應用程序中,只要視圖在您的控制器中創建,您就可以使用OpenSessionInViewFilter保持會話打開。

5.)我認爲您也可以直接使用AOP。你可以有一個方面保持會議打開一個任意的Joinpoint,但我沒有真正的經驗,不能更具體;)

希望有幫助...