我在@Async服务层方法上使用注释。
@Async
当我紧急加载@OneToMany集合字段时,一切工作正常,但是当我尝试访问LAZY加载的元素时,我发现Hibernate SessionImplementor对象session为null。这显然给了我一个例外:
SessionImplementor
session
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会话以便将对象延迟加载到@Async上下文中?
编辑
这是我的trancactionManager / entityManager配置
<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保留Spring的事务上下文。这意味着您的SessionFactory仅可用于调度您的请求的线程,因此,如果创建一个新线程,您将获得null和相应的异常。
null
您的@Async方法所做的是使用TaskExecutor在另一个线程中运行您的方法。因此,您的服务正在发生上述问题。
我引用了Spring的JpaTransactionManager文档:
单个JPA EntityManagerFactory的PlatformTransactionManager实现。 将JPA EntityManager从指定的工厂绑定到线程 ,可能允许每个工厂一个线程绑定的EntityManager。SharedEntityManagerCreator和@PersistenceContext知道线程绑定的实体管理器,并自动参与此类事务。支持该事务管理机制的JPA访问代码需要使用其中一种。
如果要保留注释,则应查看Hibernate CurrentSessionContext并以某种方式自行管理会话。