lazyinitializationexception打开了“在视图中打开”

b09cbbtk  于 2021-07-16  发布在  Java
关注(0)|答案(1)|浏览(348)

在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);

    ...

}

关于如何保持更新查询有什么想法吗?缓存重置是必须的,因为它不会随查询更新。

gcxthw6b

gcxthw6b1#

其实这个问题与 Session 在这里,它是一个修改查询,用于清除持久性上下文,而您保存到web层的对象现在是一个分离的对象。
如果在错误消息中检查类 AbstractPersistenceCollection 它有一个函数,用来检查 session 有没有

protected boolean isConnectedToSession() {
        return session != null
                && session.isOpen()
                && session.getPersistenceContextInternal().containsCollection( this );
    }

如你所见,这是 && 条件,最后一个条件是检查持久性上下文是否包含集合,这可能会在您的情况下引发错误,而不管会话是否打开。

相关问题