LazyInitializationException из-за отсутствия сеанса, определенного в «родительском» контексте приложения в Hibernate 3 в запланированном приложении Spring с использованием аннотаций - PullRequest
0 голосов
/ 10 марта 2011

Я довольно новичок как в Hibernate3, так и в Spring3, и у меня возникла проблема, связанная с инициализацией отложенных ссылок объекта hibernate.

У меня есть полный дао и сервис. Доменные объекты создаются с использованием hbm2java и файла обратного инжиниринга. Я следовал рекомендациям по использованию аннотаций (@Transactional) в своих сервисных объектах. (Это руководство было ОЧЕНЬ полезно для меня http://carinae.net/2009/11/layered-architecture-with-hibernate-and-spring-3/)

Проблема, с которой я столкнулся, заключается в том, что у меня есть следующая пружинная конфигурация в моем service.jar для обработки аннотаций и управления транзакциями:

  <context:annotation-config />
  <context:component-scan base-package="com.barlingbay.dodmerb.persistence" />

    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="configLocation">
            <value>classpath:hibernate.cfg.xml</value>
        </property>
    </bean>

  <tx:annotation-driven/>  

  <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>

  <bean id="transactionManager"
    class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
  </bean>

Мой hibernate.cfg.xml - это просто список моих данных источника данных и сопоставлений аннотаций объектов домена.

Я использую сервисный слой и слой дао.

@Service
public class ApplicantEventServiceImpl implements ApplicantEventService {

  @Autowired(required = true)
  private ApplicantEventDao appEventDao;

  @Transactional
  public List<ApplicantEvent> getEvents() {
    return this.appEventDao.getPendingEvents();
  }

и слой дао

@Repository
public class ApplicantEventDaoImpl implements ApplicantEventDao {

  @Autowired(required = true)
  private SessionFactory sessionFactory;

  public List<ApplicantEvent> getPendingEvents() {
    sessionFactory.getCurrentSession().beginTransaction(); // (If I don't have this, my junit test fails because of no active transaction, but that's a different issue)
    return sessionFactory.getCurrentSession()
        .createQuery("from ApplicantEvent").list();

  }

Эта коллекция кода упакована как модуль maven и включена в качестве зависимости в другой весенний проект, который является модулем планирования и рабочего процесса, который я разрабатываю. Соответствующее applicationContext.xml info

<bean id="workflowStepper" class="com.barlingbay.merb.scheduler.WorkflowStepper" />

<bean id="jobDetailWorkflowStepper"
    class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"
    p:targetObject-ref="workflowStepper" p:targetMethod="execute" />

<bean id="triggerJobDetailTicketRegistryCleaner" class="org.springframework.scheduling.quartz.SimpleTriggerBean"
    p:jobDetail-ref="jobDetailWorkflowStepper" p:startDelay="2000"
    p:repeatInterval="5000" />

<bean id="scheduler"
    class="com.barlingbay.merb.scheduler.AutowiringSchedulerFactoryBean" />

И базовый Workflow.java:

public class WorkflowStepper implements IWorkflowStepper,
    ApplicationContextAware {

  private final Logger       LOG = Logger.getLogger(this.getClass());
  private ApplicationContext applicationContext;

  // @Transactional
  public void execute() {
    ApplicantEventService appEvent = (ApplicantEventService) applicationContext
        .getBean("applicantEventServiceImpl");
    List<ApplicantEvent> events = appEvent.getEvents();

    for (ApplicantEvent event : events) {
      try {
        LOG.info(event.getApplicant().getUsername() + "[" + event.getName()
            + "]");
....

Я получаю (и понимаю, почему я получаю) исключение LazyInitializationException во время выполнения инструкции LOG.info. Транзакция управляется контекстом spring-hibernate во включенной зависимой службе и не доступна в этом контексте. Что я не понимаю, так это правильный способ включить управление транзакциями в этот уровень (и далее), чтобы предотвратить исключение LazyInitializationException. Я попытался просто добавить

<bean id="txInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor" />

к контексту приложения бизнес-уровня, который жаловался на то, что не может видеть менеджер транзакций, определенный в зависимости службы. Однако, если я добавлю @Transactional в .execute () степпера Workflow, он «унаследует» конфигурацию от зависимости.

Чего мне не хватает?

1 Ответ

0 голосов
/ 13 марта 2011

Вы можете бороться с Lazy-инициализацией, используя перехватчик OpenEntityManagerInView в вашем приложении.В противном случае вы можете вызвать метод getter для одного из ApplicationEvent в списке событий внутри метода getPendingEvents ().Это с готовностью загрузит объекты внутри списков.

РЕДАКТИРОВАТЬ: вы, кажется, не используете JPA в вашем приложении, поэтому OpenEntityManagerInView может не быть объектом.Второй вариант все еще должен работать.

...