gpt4 book ai didi

hibernate - Spring/Hibernate 延迟加载需要帮助

转载 作者:行者123 更新时间:2023-12-03 06:54:07 29 4
gpt4 key购买 nike

我知道这个问题已经讨论过很多次了。我只是不明白这是如何工作的或者我的错误在哪里。
我认为给你一个简化的例子是向你展示我正在尝试做什么以及我正在采取什么假设的最佳方式......

我有一个带有名称的产品类。该名称是一个惰性字符串属性。

我的 DAO:

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

我的服务接口(interface):

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 打开,我对吗?如果是这样,为什么 session 在加载产品对象后关闭?

我在某处读到我也可以使用 OpenSessionInViewInterceptor,但我无法使其工作。您将如何将该拦截器添加到这个小示例中?

对于其工作原理是否存在任何代码错误或误解?

你知道我可以下载什么简单的示例代码来检查它是如何工作的吗?

提前致谢,内乌基诺

最佳答案

问题是 HibernateInterceptor 从 ProductService getProduct() 返回后关闭 session

来自API DOCs:

此拦截器在方法调用之前将新的 Hibernate Session 绑定(bind)到线程,然后在出现任何方法结果时关闭并删除它。如果已经有一个预绑定(bind)的 Session(例如来自 HibernateTransactionManager 或来自周围的 Hibernate 拦截方法),则拦截器只需参与其中即可。

并为以下对ProductService.getProductName()的调用打开一个新的。新创建的 session 不知道您在上一个 session 中从数据库中获取的产品实体。

您有多种可能性来解决此问题:

1.) 添加一个急切加载名称的方法,并在特定上下文中使用它,这是显而易见的;)

2.) 您可以在 ProductService.getProductName 中调用 Product.getName() 之前使用 Session.update(myProductEntity) 将实体重新附加到事件 session ()

3.) 您可以将其全部包装在一个事务中,包装方法调用 ProductService.getProduct()ProductService.getProductName() 参与该事务。请参阅 Transaction Propagation

4.) 在 Web 应用程序中,只要在 Controller 中创建 View ,您就可以使用 OpenSessionInViewFilter 来保持 session 打开状态

5.) 我想你也可以直接使用AOP。您可以让 session 在任意连接点上保持打开状态,但我在那里没有真正的经验,无法更具体;)

希望有帮助...

关于hibernate - Spring/Hibernate 延迟加载需要帮助,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2976888/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com