在spring.jpa.open in view=true的spring boot2.1.2项目中,我们(在几年没有出现这种问题之后)在调用lazy集合时面临lazyinitializationexception。
jpa调试的堆栈跟踪(logging.level.org.springframework.orm.jpa=debug)表明,如预期的那样,在执行请求期间,会话没有关闭,这与提交的单个事务无关:
2021-03-22 23:37:25.198 DEBUG 22668 --- [io-8020-exec-10] o.s.orm.jpa.JpaTransactionManager : Committing JPA transaction on EntityManager [SessionImpl(211207390<open>)]
2021-03-22 23:37:25.199 DEBUG 22668 --- [io-8020-exec-10] o.s.orm.jpa.JpaTransactionManager : Not closing pre-bound JPA EntityManager after transaction
2021-03-22 23:37:25.199 DEBUG 22668 --- [io-8020-exec-10] o.s.orm.jpa.JpaTransactionManager : Found thread-bound EntityManager [SessionImpl(211207390<open>)] for JPA transaction
2021-03-22 23:37:25.199 DEBUG 22668 --- [io-8020-exec-10] o.s.orm.jpa.JpaTransactionManager : Creating new transaction with name [org.springframework.data.jpa.repository.support.SimpleJpaRepository.findAll]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly
2021-03-22 23:37:25.200 DEBUG 22668 --- [io-8020-exec-10] o.s.orm.jpa.JpaTransactionManager : Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@6f7a9974]
2021-03-22 23:37:25.200 DEBUG 22668 --- [io-8020-exec-10] o.s.orm.jpa.JpaTransactionManager : Initiating transaction commit
2021-03-22 23:37:25.201 DEBUG 22668 --- [io-8020-exec-10] o.s.orm.jpa.JpaTransactionManager : Committing JPA transaction on EntityManager [SessionImpl(211207390<open>)]
2021-03-22 23:37:25.202 DEBUG 22668 --- [io-8020-exec-10] o.s.orm.jpa.JpaTransactionManager : Not closing pre-bound JPA EntityManager after transaction
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.opsfactor.planning.model.domain.cluster.produto.ClusterProdutos.regrasAlocacaoClusterProdutos, could not initialize proxy - no Session
at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:597)
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:216)
at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:576)
at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:147)
at org.hibernate.collection.internal.PersistentSet.iterator(PersistentSet.java:188)
at com.opsfactor.planning.model.projection.configuration.parametros.ClusterEParametrosProjection.getClusterProdutosDeMaterial(ClusterEParametrosProjection.java:740)
即使会话没有关闭,错误也会出现,总是在同一点上。正在执行的实体和代码是:
@Entity
public class ClusterProdutos implements Serializable {
...
---------> collection generating error
@OneToMany(mappedBy = "clusterProdutos",cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true)
private Set<RegraAlocacaoClusterProdutos> regrasAlocacaoClusterProdutos = new HashSet<>();
...
}
我还没有发现任何关于spring.jpa.open in view=true出现这种异常的帖子/评论,因此除了解决问题之外,我还想了解它背后的原因。可能急于获取集合或只是使所有内容都具有事务性会使代码运行,但它不会回答问题。
到目前为止,我们已经尝试增加连接超时、空闲超时、最大生存期和最大池大小—但没有效果。
这个错误发生在我的windows机器和我们的aws生产服务器上,这两个服务器运行在它们的linux版本上,数据库是mysql 8
更新:
当我注解掉下面的repository调用时,错误就会停止,这是在前一个实体示例化之前进行的:
@Repository
public interface ProductionPlanLinhaRepository extends JpaRepository<ProductionPlanLinha,ProductionPlanLinhaCompositeKey> {
...
@Transactional
@Modifying(clearAutomatically = true, flushAutomatically = true) // https://www.baeldung.com/spring-data-jpa-modifying-annotation
@Query("UPDATE ProductionPlanLinha ppl "
+ "SET ppl.quantidadeSugestaoProducaoBaselineAtendida = ppl.quantidadeSugestaoProducaoBaseline, "
+ "ppl.quantidadeSugestaoProducaoItensNovosAtendida = ppl.quantidadeSugestaoProducaoItensNovos, "
+ "ppl.quantidadeSugestaoProducaoUpliftAtendida = ppl.quantidadeSugestaoProducaoUplift, "
+ "ppl.quantidadeSugestaoProducaoAjusteDemandaAtendida = ppl.quantidadeSugestaoProducaoAjusteDemanda, "
+ "ppl.quantidadeSugestaoProducaoAjusteSupplyAtendida = ppl.quantidadeSugestaoProducaoAjusteSupply "
+ "WHERE ppl.productionPlanLinhaCompositeKey.supplyPlan.id = :supplyPlanId")
public void resetPlanoProducaoRestritoBySupplyPlanId(Long supplyPlanId);
...
}
关于如何保持更新查询有什么想法吗?缓存重置是必须的,因为它不会随查询更新。
1条答案
按热度按时间gcxthw6b1#
其实这个问题与
Session
在这里,它是一个修改查询,用于清除持久性上下文,而您保存到web层的对象现在是一个分离的对象。如果在错误消息中检查类
AbstractPersistenceCollection
它有一个函数,用来检查session
有没有如你所见,这是
&&
条件,最后一个条件是检查持久性上下文是否包含集合,这可能会在您的情况下引发错误,而不管会话是否打开。