gip*_*ani 8 java spring hibernate hibernate-session
我在@Async服务层方法上使用注释.
当我EAGERLY加载@OneToMany集合字段时,一切正常,但是当我尝试访问LAZY加载的元素时,我发现Hibernate SessionImplementor对象session为null.这显然给了我一个例外:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role:
....
Run Code Online (Sandbox Code Playgroud)
这是我的收藏领域:
@OneToMany(mappedBy="abc", fetch=FetchType.LAZY, cascade=CascadeType.REMOVE)
@OrderBy(value="xsd asc")
@JsonIgnore
private Set<Item> items = new HashSet<Item>();
Run Code Online (Sandbox Code Playgroud)
如何绑定hibernate会话以便LAZELY在@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"/>
Run Code Online (Sandbox Code Playgroud)
小智 10
我有同样的问题,花了几天时间试图找到解决方案,最后得到了解决方案.我想与那些可能遇到同样问题的人分享我找到的细节.
1st - 您的@Async注释方法应该在一个单独的bean中声明,而不是在@Controller- 或 - @RestController注释bean中声明.
第二 - 你当然需要声明@Transactional从声明的方法中调用的@Async方法.但是,@Async必须定义从方法调用的第一个方法@Transactional.我@Transactional在方法执行堆栈中使用了第二级或第三级的方法,因此问题没有解决,我花了两天时间试图弄清楚发生了什么.
所以最好的办法是
@Controller
ControllerBean {
@Autowired
AsyncService asyncService;
public controllerMethod() {
asyncService.asyncMethod();
}
}
@Service
AsyncService {
@Autowired
TransactionalService transactionalService;
@Async
public asyncMethod() {
transactionalService.transactionalMethod();
}
}
@Service
TransactionalService {
@Autowired
SomeOtherService someOtherService;
@Autowired
EntityRepository entityRepository;
@Transactional
public transactionalMethod() {
Entity entity = entityRepository.findOne(12345);
someOtherService.doWork(entity);
}
}
@Service
SomeOtherService {
@Autowired
EntityRepository entityRepository;
@Transactional
public doWork(Entity entity) {
// fetch lazy properties, save, etc. without any session problems...
entity.getLazyProperties();
entityRepository.save(entity);
}
}
Run Code Online (Sandbox Code Playgroud)
使用ThreadLocals保留Spring的事务上下文.这意味着您的SessionFactory仅可用于调度您的请求的线程,因此,如果您创建新线程,您将获得null一个相应的异常.
您的@Async方法所做的是使用TaskExecutor在另一个线程中运行您的方法.所以上面描述的问题发生在你的服务上.
我引用Spring的JpaTransactionManager文档:
单个JPA EntityManagerFactory的PlatformTransactionManager实现.将JPA EntityManager从指定的工厂绑定到线程,可能允许每个工厂使用一个线程绑定的EntityManager.SharedEntityManagerCreator和@PersistenceContext知道线程绑定的实体管理器并自动参与此类事务.支持此事务管理机制的JPA访问代码需要使用其中任何一个.
如果你想保留你的注释,那么你应该看看Hibernate CurrentSessionContext并以某种方式自己管理会话.
有关详细信息,请参阅此问题.
| 归档时间: |
|
| 查看次数: |
7734 次 |
| 最近记录: |