由于“父”中没有定义会话而导致 LazyInitializationException使用注释的模块化 Spring 应用程序中 Hibernate 3 中的应用程序上下文

发布于 2024-10-21 01:20:23 字数 3937 浏览 7 评论 0原文

我对 Hibernate3 和 Spring3 都很陌生,并且遇到了与初始化 hibernate 对象的惰性引用相关的问题。

我有一个完全包含的 dao 和服务。域对象是使用 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();
  }

和 dao 层

@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 添加到工作流步进器的 .execute() 中,它会从依赖项“继承”配置。

我缺少什么?

I am fairly new to both Hibernate3 and Spring3, and I'm having an issue related to initializing lazy references of a hibernate object.

I have a fully contained dao and service. The domain objects are created using hbm2java and a reverse engineering file. I have followed some best practices I have found using Annotations (@Transactional) on my service objects. (This guide was VERY helpful to me http://carinae.net/2009/11/layered-architecture-with-hibernate-and-spring-3/)

The issue that I am having is that I have the following spring configuration in my service.jar for annotation processing and transaction management:

  <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>

My hibernate.cfg.xml is simply a listing of my datasource details and the annotation mappings of the domain objects.

I am using a service layer and a dao layer.

@Service
public class ApplicantEventServiceImpl implements ApplicantEventService {

  @Autowired(required = true)
  private ApplicantEventDao appEventDao;

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

and a dao layer

@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();

  }

This collection of code is packaged as a maven module and is included in as a dependency in another spring project which is a scheduling and workflow module that I am developing. Relevant 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" />

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

I get (and I understand why I get) a LazyInitializationException during the LOG.info statement. The transaction is managed by the spring-hibernate context in the included service maven dependency and is not available in this context. What I don't understand is the proper way to include the transaction management into this layer (and beyond) to prevent the LazyInitializationException. I tried simply adding

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

to the business layer's application context, which it complained that it couldn't see the transactionmanager defined in the service dependency. However, if I do add @Transactional to the .execute() of the Workflow stepper, it does "inherit" the configuration from the dependency.

What am I missing?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

小嗲 2024-10-28 01:20:23

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

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

You can fight through Lazy-initialization using an OpenEntityManagerInView interceptor in your application. Else you can call some getter method on one of the ApplicationEvent in the list of events inside the getPendingEvents() method. This will eagerly load the objects inside the lists.

EDIT: You dont seem to use JPA in your application so OpenEntityManagerInView might not be an object. The second option should still work.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文