Немного фона: Я использую Spring и Hibernate для создания действительно простой структуры домена/дао/сервиса. Я также использую Autowiring, чтобы вставлять все мои бобы в их счастливые места.Понимание SessionFactory весной
Во время рефакторинга у меня недавно появилось слишком популярное сообщение об ошибке «не удалось инициализировать прокси - нет сеанса» при попытке получить доступ к свойству 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, может позвонить, чтобы получить человека, он не может получить доступ к Pet, поскольку моя сессия закрыта.
Итак, я думаю, что неясно, когда я теряю сессию спящего режима. Все конфиги выглядят отлично, и DAO вводят в мой помощник, как будто он используется для ввода в мой сервис. Я не знаю, почему моя служба может заставить Пэт просто отлично, но мой помощник не может.
Любая помощь с пониманием этого «SessionFactory mystery» хорошо оценена. Я понимаю, что это может быть сложный вопрос, поэтому ссылки на некоторые хорошие материалы для чтения будут качать.
С тех пор я сменил код на FetchType.EAGER (работает отлично), но эта загадка сжигает целое в моем мозгу :).
Per запросов, здесь есть (упрощенно) смотреть в моей конфигурации:
<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 в помощнике:
@Autowired
private PersonDao personDao;
Очень интересно. Я собираюсь изучить фильтры, так как это то, о чем я мало что знаю. – Stephano
Добавлен в какую-то конфигурацию, которую я использую. AnnotationSessionFactoryBean может показаться немного странным, поскольку я пытаюсь упростить эту идею для этого сообщения (это на практике немного сложнее) – Stephano
@Stephano - Спасибо за обновление. Думаю, ваш DAO реализован с использованием HibernateDaoSupport? Из деталей здесь я не вижу, как бы это сработало раньше. Возможно, вам просто повезло! (Или более реалистично, есть дополнительные подробности, которые могли бы устранить тайну.существует ли какое-либо управление транзакциями?) Возможно, ваши DAO вызывали другие DAO, и поэтому сеанс был открыт в течение всего первого вызова, который охватывает вложенные вызовы. Связано: http://stackoverflow.com/questions/2145024/lazy-loading-with-spring-hibernatedaosupport – mdma