理解Spring中的SessionFactory

时间:2010-07-18 18:30:07

标签: java hibernate spring

一点背景:我正在使用Spring和Hibernate来创建一个非常简单的域/ dao /服务结构。我也在使用Autowiring将我所有的豆子注入他们喜欢的地方。

在重构时,我最近在尝试访问我的hibernate对象上的FetchType.LAZY属性时得到了一个非常流行的错误消息“无法初始化代理 - 无会话”。它是这样的:

public class Person {

...

 @ManyToOne(cascade = {}, fetch = FetchType.LAZY)
 @JoinColumn(name = "pet_id", nullable = false)
 public Pet getPet() {
  return pet;
 }
...
}

我曾经有一个访问Pet属性的PersonService bean,并且没有遇到任何麻烦。但是,我最近重构了代码,以便PersonH​​elper查看它而不是查看Pet的PersonService。虽然我的帮助bean可以看到PersonDao,但是可以打电话来获取该人,但是当我的会话关闭时,它无法访问Pet。

所以,我认为我不清楚何时松开hibernate会话。所有的配置看起来都很好,DAO正在注入我的助手,就像以前注入我的服务一样。我不确定为什么我的服务可以让宠物好,但我的助手不能。

理解这个“SessionFactory之谜”的任何帮助都非常感谢。我意识到这可能是一个复杂的主题,所以链接到一些好的阅读材料会摇滚。

我已经将代码更改为FetchType.EAGER(工作正常),但是这个谜语在我的大脑中燃烧了一个整体:)。

根据请求,这里是(简化)查看我的配置:

    <bean id="personSvc" class="org.comp.service.impl.PersonServiceImpl" />
    <bean id="personHelper" class="org.comp.service.helper.PersonHelper" />

    <bean id="personDao" class="org.comp.dao.hibernate.HibPersonDaoImpl">
        <property name="sessionFactory">
            <ref bean="sessionFactory" />
        </property>
    </bean>

...

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close">
    </bean>

    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource">
            <ref bean="dataSource" />
        </property>
        <property name="packagesToScan" value="org.comp.domain"/>
        <property name="schemaUpdate" value="true" />
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.show_sql">false</prop>

                <prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider
                </prop>
                <prop key="hibernate.cache.provider_configuration_file_resource_path">/hibernate-ehcache.xml</prop>
            </props>
        </property>
    </bean>
<bean id="transactionManager"
    class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory">
        <ref bean="sessionFactory"/>
    </property>
</bean>

DAO自动装入帮助者:

@Autowired
private PersonDao personDao;

2 个答案:

答案 0 :(得分:3)

在没有看到PersonService的代码/上下文配置的情况下,我只能猜测它在重构之前的工作原理。如果您使用HibernateInterceptor围绕DAO方法包装会话管理,则会在方法完成后立即关闭会话,除非事先打开(例如OpenSessionInViewFilter)。< / p>

我的猜测是HibernateInterceptor的范围可能在重构期间发生了变化,因此会话现在在获取数据后立即关闭。您可能希望扩展HibernateInterceptor的范围以覆盖您的服务/业务方法,以便会话保持足够长的时间以便延迟提取工作,或者使用OpenSessionInViewFilter来确保会话永远可用。

答案 1 :(得分:1)

OSIV始终是必须阅读的,无论您是否正在编写基于Web的应用程序。

我在Spring bean的方法(at the service layer)中使用@Transactional标记,让Spring以这种方式为我管理会话(Spring默认处理每个线程的Hibernate会话)。