如何修复org.hibernate.LazyInitializationException - could not initialize proxy - no Session错误

283

我遇到了以下异常:

Exception in thread "main" org.hibernate.LazyInitializationException: could not initialize proxy - no Session
    at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:167)
    at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:215)
    at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:190)
    at sei.persistence.wf.entities.Element_$$_jvstc68_47.getNote(Element_$$_jvstc68_47.java)
    at JSON_to_XML.createBpmnRepresantation(JSON_to_XML.java:139)
    at JSON_to_XML.main(JSON_to_XML.java:84)

当我尝试从主函数调用以下代码时:

Model subProcessModel = getModelByModelGroup(1112);
System.out.println(subProcessModel.getElement().getNote());

我首先实现了getModelByModelGroup(int modelgroupid)方法,代码如下:

public static Model getModelByModelGroup(int modelGroupId, boolean openTransaction) {

    Session session = SessionFactoryHelper.getSessionFactory().getCurrentSession();     
    Transaction tx = null;

    if (openTransaction) {
        tx = session.getTransaction();
    }

    String responseMessage = "";

    try {
        if (openTransaction) {
            tx.begin();
        }
        Query query = session.createQuery("from Model where modelGroup.id = :modelGroupId");
        query.setParameter("modelGroupId", modelGroupId);

        List<Model> modelList = (List<Model>)query.list(); 
        Model model = null;

        for (Model m : modelList) {
            if (m.getModelType().getId() == 3) {
                model = m;
                break;
            }
        }

        if (model == null) {
            Object[] arrModels = modelList.toArray();
            if (arrModels.length == 0) {
                throw new Exception("Non esiste ");
            }

            model = (Model)arrModels[0];
        }

        if (openTransaction) {
            tx.commit();
        }

        return model;

   } catch(Exception ex) {
       if (openTransaction) {
           tx.rollback();
       }
       ex.printStackTrace();
       if (responseMessage.compareTo("") == 0) {
           responseMessage = "Error" + ex.getMessage();
       }
       return null;
    }
}

后来我遇到了异常。然后有个朋友建议我总是测试会话并获取当前会话以避免此错误。所以我这样做:

并得到了例外。后来朋友建议我始终测试会话并获取当前会话,以避免出现这种错误。于是我就这么做了:

public static Model getModelByModelGroup(int modelGroupId) {
    Session session = null;
    boolean openSession = session == null;
    Transaction tx = null;
    if (openSession) {
        session = SessionFactoryHelper.getSessionFactory().getCurrentSession(); 
        tx = session.getTransaction();
    }
    String responseMessage = "";

    try {
        if (openSession) {
            tx.begin();
        }
        Query query = session.createQuery("from Model where modelGroup.id = :modelGroupId");
        query.setParameter("modelGroupId", modelGroupId);

        List<Model> modelList = (List<Model>)query.list(); 
        Model model = null;

        for (Model m : modelList) {
            if (m.getModelType().getId() == 3) {
                model = m;
                break;
            }
        }

        if (model == null) {
            Object[] arrModels = modelList.toArray();
            if (arrModels.length == 0) {
                throw new RuntimeException("Non esiste");
            }

            model = (Model)arrModels[0];

            if (openSession) {
                tx.commit();
            }
            return model;
        } catch(RuntimeException ex) {
            if (openSession) {
                tx.rollback();
            }
            ex.printStackTrace();
            if (responseMessage.compareTo("") == 0) {
                responseMessage = "Error" + ex.getMessage();
            }
            return null;        
        }
    }
}

但是仍然会得到相同的错误。我已经阅读了很多关于这个错误的内容,并找到了一些可能的解决方案。其中一个是设置lazyLoad为false,但我不允许这样做,所以建议我控制session。

25个回答

4
这意味着您在代码中使用JPA或Hibernate并对数据库执行修改操作,但没有进行业务逻辑事务处理。 解决此问题的简单方法是将您的代码标记为@Transactional。

谢谢!我在一个方法上遇到了问题,而在其他类似的方法上却运行得很好。多亏了你,我发现我只是忘记将其设置为事务性,这为我解决了问题。+1 - marcel

3
  • springBootVersion = '2.6.7'
  • hibernate = 5.6.8.Final'

我遇到了错误:

MyEntity myEntity = myEntityRepository.getById(id);

我改成了这样:

MyEntity myEntity = myEntityRepository.findById(id).orElse(null);

我在实体中添加了@ManyToOne(fetch = FetchType.EAGER)


3
这里有几个很好的答案,涵盖了这个错误的广泛范围。我遇到了一个特定的情况,与Spring Security有关,有一个快速但可能不是最优解的修复方法。
在用户授权过程中(在登录并通过身份验证后立即),我正在测试一个自定义类中的用户实体是否具有特定权限,该类扩展了SimpleUrlAuthenticationSuccessHandler。
我的用户实体实现了UserDetails,并拥有一组延迟加载的角色,导致抛出了“org.hibernate.LazyInitializationException - could not initialize proxy - no Session”异常。将该Set从“fetch=FetchType.LAZY”更改为“fetch=FetchType.EAGER”可解决此问题。

2
在Spring应用中,只需添加以下内容。
@Transactional(readOnly = true)

在您的Function上。

提醒导入Spring Transactional注解

import org.springframework.transaction.annotation.Transactional;


2

2

1
如果您正在使用Grail's框架,可以在域类中的特定字段上使用Lazy关键字来解决延迟初始化异常。例如:
class Book {
    static belongsTo = [author: Author]
    static mapping = {
        author lazy: false
    }
}

找到更多相关信息这里

1
在我的情况下,一个错放的 session.clear() 导致了这个问题。

1

当我已经在使用@Transactional(value=...)并且正在使用多个事务管理器时,这种情况发生在我身上。

我的表单发送回已经有@JsonIgnore的数据,因此从表单发送回来的数据是不完整的。

最初我使用了反模式解决方案,但发现它非常慢。我通过将其设置为false来禁用它。

spring.jpa.properties.hibernate.enable_lazy_load_no_trans=false

解决方法是确保首先从数据库中检索任何具有未加载数据的延迟加载对象。
Optional<Object> objectDBOpt = objectRepository.findById(object.getId());

if (objectDBOpt.isEmpty()) {
    // Throw error
} else {
    Object objectFromDB = objectDBOpt.get();
}

简而言之,如果你已经尝试了其他所有的答案,只需确保在数据库查询中首先从数据库加载数据,如果你没有提供所有的@JsonIgnore属性并且正在使用它们,则应返回检查。

0
在我的JAX-RS应用程序中,当我尝试获取所有部门时,我遇到了这个错误。我不得不向两个类的属性添加@JsonbTransient注释。我的实体是Department和Employee,数据库关系是多对多。

Employee.java

...
@ManyToMany
@JoinTable(
        name = "emp_dept",
        joinColumns = {@JoinColumn(name = "emp_id", referencedColumnName = "id")},
        inverseJoinColumns = {@JoinColumn(name = "dept_id", referencedColumnName = "id")}
)
@JsonbTransient
private Set<Department> departments = new HashSet<Department>();
...

Department.java

...
@ManyToMany(mappedBy = "departments")
@JsonbTransient
private Set<Employee> employees = new HashSet<Employee>();
...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接