0

我对 Hibernate3 和 Spring3 都很陌生,我遇到了一个与初始化休眠对象的惰性引用有关的问题。

我有一个完全包含的道和服务。域对象是使用 hbm2java 和逆向工程文件创建的。我遵循了一些在我的服务对象上使用注释 (@Transactional) 时发现的最佳实践。(本指南对我非常有帮助http://carinae.net/2009/11/layered-architecture-with-hibernate-and-spring-3/

我遇到的问题是我的 service.jar 中有以下 spring 配置,用于注释处理和事务管理:

  <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 只是我的数据源详细信息和域对象的注释映射的列表。

我正在使用服务层和 dao 层。

@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 模块,并作为依赖项包含在另一个 spring 项目中,该项目是我正在开发的调度和工作流模块。相关 applicationContext.xml 信息

<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()
            + "]");
....

在 LOG.info 语句期间,我得到(并且我理解为什么会得到)一个 LazyInitializationException。事务由包含的服务 maven 依赖项中的 spring-hibernate 上下文管理,在此上下文中不可用。我不明白将事务管理包含到这一层(及更高层)以防止 LazyInitializationException 的正确方法。我试着简单地添加

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

到业务层的应用程序上下文,它抱怨它看不到服务依赖项中定义的事务管理器。但是,如果我确实将 @Transactional 添加到 Workflow 步进器的 .execute() 中,它会“继承”依赖项的配置。

我错过了什么?

4

1 回答 1

0

您可以在应用程序中使用 OpenEntityManagerInView 拦截器来对抗延迟初始化。否则,您可以在 getPendingEvents() 方法内的事件列表中的一个 ApplicationEvent 上调用一些 getter 方法。这将急切地加载列表中的对象。

编辑:您似乎没有在您的应用程序中使用 JPA,因此 OpenEntityManagerInView 可能不是一个对象。第二个选项应该仍然有效。

于 2011-03-13T11:43:58.077 回答