org.hibernate.LazyInitializationException: 无法延迟初始化角色集合:没有会话或会话已关闭。

3
我将我的实体定义如下:
 package com.drishti.training.dbentity;

import java.util.List;

import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.Table;

import com.drishti.dacx.core.framework.ameyoentitytypes.AbstractDBEntity;

/**
 *
 */
@Entity
@Table(name = "template")
public class TemplateDBEntity extends AbstractDBEntity {

    String template_name, organisationId;

    @Column(name = "organisation_id", nullable = false)
    public String getOrganisationId() {
        return organisationId;
    }

    public void setOrganisationId(String organisationId) {
        this.organisationId = organisationId;
    }

    private String templateId;
    //    private List<Integer> listOfTrainingIds;

    private List<String> listOfTrainingIds;

    @Id
    @Column(name = "template_id", nullable = false)
    public String getTemplateId() {
        return templateId;
    }

    public void setTemplateId(String templateId) {
        this.templateId = templateId;
    }

    @ElementCollection(targetClass = String.class)
    @CollectionTable(name = "template_id_vs_training_id", joinColumns = @JoinColumn(name = "template_id"))
    @Column(name = "training_id", nullable = false)
    public List<String> getListOfTrainingIds() {
        return listOfTrainingIds;
    }

    public void setListOfTrainingIds(List<String> listOfTrainingIds) {
        this.listOfTrainingIds = listOfTrainingIds;
    }

    @Column(name = "template_name")
    public String getName() {
        return template_name;
    }

    public void setName(String name) {
        this.template_name = name;
    }
}

同时

另一个表格是

create table template_id_vs_training_id
(
    template_id varchar references template(template_id) on delete cascade,
    training_id varchar references training(training_id) on delete cascade,
    PRIMARY KEY (template_id,training_id)
);

但是当我加载TemplateDBEntity时,它提供了上述报错。

使用CollectionTable的特定原因是什么? - Mudassar
也分享存储库/查询的代码 - Mudassar
1个回答

7

LazyInitializationException,如Hibernate文档所述:

表示在会话上下文之外尝试访问尚未获取的数据。例如,在关闭会话后访问未初始化的代理或集合时。

此异常的唯一原因是listOfTrainingIds属性,因为它是默认懒加载的@ElementCollection,因此可以采取以下措施:

  • 确保您在事务内访问listOfTrainingIds属性(您的实体可以使用可用会话来获取您的集合)。

  • 或使其渴望@ElementCollection(fetch = FetchType.EAGER),但请注意,每次从数据库选择实体时,您的集合也将被急切地加载,即使您不需要它,这可能会影响性能。

  • 或在Hibernate查询中使用fetch关键字(如果您正在使用查询来加载实体):

    List<TemplateDBEntity> TemplateDBEntitys = session.createQuery(
    "select t from TemplateDBEntity t join fetch t.listOfTrainingIds", 
    TemplateDBEntity.class).getResultList();
    // In class...
    @FetchProfile(
      name = "withListOfTrainingIds",
      fetchOverrides = {@FetchProfile.FetchOverride(mode = FetchMode.JOIN, association = "listOfTrainingIds", entity = TemplateDBEntity.class)})
    public class TemplateDBEntity extends AbstractDBEntity {
      //...
    }

    // To get your entity
    session.enableFetchProfile("withListOfTrainingIds");
    System.out.println(session.get(TemplateDBEntity.class, templateId));
    session.disableFetchProfile("withListOfTrainingIds");

我更倾向于最后两个选项,因为即使你保持集合懒加载,Hibernate也只会对数据库执行一次查询,这对性能更好。


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