Понимание SessionFactory весной - PullRequest
4 голосов
/ 18 июля 2010

Немного предыстории: я использую Spring и Hibernate для создания действительно простой структуры домен / дао / сервис. Я также использую Autowiring для ввода всех своих бобов в их счастливые места.

Во время рефакторинга я недавно получил слишком популярное сообщение об ошибке «Не удалось инициализировать прокси - нет сеанса» при попытке доступа к свойству FetchType.LAZY в моем спящем объекте. Это выглядит примерно так:

public class Person {

...

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

Раньше у меня был компонент PersonService, который обращался к свойству Pet, и у меня не было проблем с этим. Тем не менее, я недавно провела рефакторинг кода, чтобы вместо PersonService, смотрящего на Pet, PersonHelper смотрел на него. В то время как мой компонент-помощник может видеть PersonDao, он может позвонить, чтобы получить человека, но он не может получить доступ к питомцу, так как моя сессия закрыта.

Итак, я думаю, что мне непонятно, когда я теряю свою спящую сессию. Все конфиги выглядят нормально, и DAO внедряется в моего помощника, точно так же, как он использовался для моего сервиса. Я не уверен, почему мой сервис мог получить Pet просто отлично, но мой помощник не может.

Любая помощь с пониманием этой "тайны 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 ]

3 голосов
/ 18 июля 2010

Не видя конфигурацию кода / контекста для PersonService, я могу только догадываться, почему она работала до рефакторинга. Если вы используете HibernateInterceptor , чтобы обернуть управление сеансом вокруг ваших методов DAO, тогда сеанс закрывается сразу после завершения метода, если он не был открыт заранее (например, OpenSessionInViewFilter ).

Я предполагаю, что область действия HibernateInterceptor могла измениться во время рефакторинга, так что теперь сеанс закрывается сразу после выборки данных. Возможно, вы захотите взглянуть на расширение области действия HibernateInterceptor, чтобы охватить ваши сервисные / бизнес-методы, чтобы сеанс сохранялся достаточно долго для работы с отложенной выборкой, или, альтернативно, используйте OpenSessionInViewFilter, который гарантирует, что сеанс всегда имеется.

1 голос
/ 18 июля 2010

OSIV всегда необходимо прочитать, пишете вы веб-приложение или нет.

Я использую тег @Transactional в методах моих bean-компонентов Spring ( на уровне службы ) и позволяю Spring таким образом управлять сессией для меня (Spring обрабатывает Hibernate-сеанс для каждого потока с помощьюдефолт).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...