Spring @Async:LAZY集合上的null hibernate会话 [英] Spring @Async: null hibernate session on LAZY collection

查看:155
本文介绍了Spring @Async:LAZY集合上的null hibernate会话的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在服务图层方法上使用 @Async 注释。

I'm using an @Async annotation on a service layer method.

当我使用时一切正常EAGERLY加载@OneToMany集合字段,但当我尝试访问LAZY加载元素时,我发现Hibernate SessionImplementor object session 是空值。这显然给了我一个例外:

Everything works fine when I EAGERLY load @OneToMany collection fields, but when I try to access LAZY loaded element I found that Hibernate SessionImplementor object session is null. That obviously give me an exception:

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role:
....    

这是我的收集字段:

@OneToMany(mappedBy="abc", fetch=FetchType.LAZY, cascade=CascadeType.REMOVE)
@OrderBy(value="xsd asc")
@JsonIgnore
private Set<Item> items = new HashSet<Item>();

我如何绑定hibernate会话以便在中加载我的对象?异步上下文?

How can I bind hibernate session in order to LAZELY load my object inside @Async context?

编辑

这是我的trancactionManager / entityManager配置

Here is my trancactionManager / entityManager configuration

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="emf"/>
</bean>

<tx:annotation-driven transaction-manager="transactionManager" />

<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="jpaVendorAdapter" ref="hibernateJpaVendorAdapter">

    </property>
    <property name="packagesToScan" value="it.domain"/>

    <property name="persistenceUnitName" value="persistenceUnit"/>
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.dialect">${hibernate.dialect}</prop>
            <prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop>
            <!--${hibernate.format_sql} -->
            <prop key="hibernate.format_sql">true</prop>
            <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
            <!-- ${hibernate.show_sql} -->
            <prop key="hibernate.show_sql">false</prop> 

            <prop key="hibernate.connection.charSet">UTF-8</prop>

            <prop key="hibernate.max_fetch_depth">3</prop>
            <prop key="hibernate.jdbc.fetch_size">50</prop>
            <prop key="hibernate.jdbc.batch_size">20</prop>

            <prop key="org.hibernate.envers.audit_table_suffix">_H</prop>
            <prop key="org.hibernate.envers.revision_field_name">AUDIT_REVISION</prop>
            <prop key="org.hibernate.envers.revision_type_field_name">ACTION_TYPE</prop>
            <prop key="org.hibernate.envers.audit_strategy">org.hibernate.envers.strategy.ValidityAuditStrategy</prop>
            <prop key="org.hibernate.envers.audit_strategy_validity_end_rev_field_name">AUDIT_REVISION_END</prop>
            <prop key="org.hibernate.envers.audit_strategy_validity_store_revend_timestamp">True</prop>
            <prop key="org.hibernate.envers.audit_strategy_validity_revend_timestamp_field_name">AUDIT_REVISION_END_TS</prop>               
        </props>
    </property>
</bean>

<jpa:repositories base-package="it.repository"
                  entity-manager-factory-ref="emf"
                  transaction-manager-ref="transactionManager"/>

<jpa:auditing auditor-aware-ref="auditorAwareBean" />
<bean id="auditorAwareBean" class="it.auditor.AuditorAwareBean"/>


推荐答案

使用 ThreadLocals 。这意味着您的SessionFactory仅可用于调度您的请求的线程,因此,如果您创建新线程,您将获得 null 和相应的异常。

Spring's transaction context is preserved using ThreadLocals. This means that your SessionFactory is only available to the thread dispatching your request thus, if you create a new thread, you will get a null and a corresponding exception.

您的 @Async 方法使用 TaskExecutor 在另一个线程中运行您的方法。所以上面描述的问题发生在您的服务上。

What your @Async method does is use a TaskExecutor to run your method in another thread. So the problem described above is happening with your service.

我引用Spring的 JpaTransactionManager docs:

I quote from the Spring's JpaTransactionManager docs:


单个JPA
EntityManagerFactory的PlatformTransactionManager实现。 将JPA EntityManager从指定的
工厂绑定到线程
,可能允许每个工厂使用一个线程绑定的
EntityManager。 SharedEntityManagerCreator和
@PersistenceContext知道线程绑定的实体管理器,
自动参与此类事务。使用JPA访问代码所需的
支持此事务管理
机制。

PlatformTransactionManager implementation for a single JPA EntityManagerFactory. Binds a JPA EntityManager from the specified factory to the thread, potentially allowing for one thread-bound EntityManager per factory. SharedEntityManagerCreator and @PersistenceContext are aware of thread-bound entity managers and participate in such transactions automatically. Using either is required for JPA access code supporting this transaction management mechanism.

如果你想保留你的注释然后你应该看看Hibernate CurrentSessionContext 并以某种方式自行管理会话。

If you want to preserve your annotation then you should take a look at Hibernate CurrentSessionContext and somehow manage the sessions yourself.

参见这个问题了解更多信息。

这篇关于Spring @Async:LAZY集合上的null hibernate会话的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆