2010-06-04 108 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,但我没有真正的经验,不能更具体;)

希望有帮助...