首页 > 解决方案 > 没有惰性的 Spring + Hibernate = LazyInitializationException

问题描述

我想从没有惰性对象/子项的表中加载所有对象并将它们列出在页面上(Thymeleaf 模板),但我每次都得到一个 LazyInitializationException。我试图将 Hibernate 实体对象转换为不包含惰性/不需要的对象但结果相同的 POJO。我也试过open-in-view parameter设置为假...

简单的例子:

家长:

@Entity
public class DocumentDbe implements Serializable {

    public DocumentDbe(){
    }
    
    @Id
    @Column(name = "id", updatable = false, nullable = false)
    private Long id;
    
    @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
    private DocumentFileDbe documentFile;
    ....
}

孩子:

@Entity
public class DocumentFileDbe implements Serializable {

    public DocumentFileDbe(){}
    
    @Id
    @Column(name = "id", updatable = false, nullable = false)
    private Long id;

    @Column
    @Lob
    private byte[] documentData;
    ...
 }

POJO:

public class DocumentDto implements Serializable {

    public DocumentDto(){
    }
    
    public DocumentDto(DocumentDbe doc){
        this.id = doc.getId();
    }
    ....
}

控制器:

@GetMapping("/list")
String getList(Model model) {
    List<DocumentDbe> docs;
    List<DocumentDto> data = new ArrayList<>();
    try (Session ses = sessionFactory.openSession()) {
        docs = ses.createQuery("FROM DocumentDbe").list();
        docs.forEach(doc -> {
            data.add(new DocumentDto(doc));
        });
    }
    model.addAttribute(MODEL_LIST_DATA, data);
    return "list";
}

编辑:抛出异常:

org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "class path resource [templates/list.html]")] with root cause
org.hibernate.LazyInitializationException: could not initialize proxy - no Session

EDIT2:DocumentDbe另一个对象的关系(这次是EAGER,所以我没有注意它),它DocumentDbe再次引用了..链式关系并创建了LazyInitializationException ...

EDIT3: 虽然
这是修改和工作控制器,没有 POJO:

@GetMapping("/list")
String getList(Model model) {
    List<DocumentDbe> docs;
    try (Session ses = sessionFactory.openSession()) {
        docs = ses.createQuery("FROM DocumentDbe ORDER BY id DESC").list();
        docs.forEach(doc -> {
            doc.setDocumentFile(null);
            doc.getHistory().forEach(log ->{
                log.setDocument(null);
            });
        });
    }

    model.addAttribute(MODEL_ADMIN_DATA, docs);
    return "list";
}

标签: spring-boothibernatelazy-loading

解决方案


在课堂DocumentDbe上,您将关系标记为 Lazy。在默认关系中@ManyToOne并且@OneToOne是 EAGER,所以如果你不想要 Lazy,你必须改变

@OneToOne(cascade = CascadeType.PERSIST)

如果你也想要 @lob 一样渴望:

@Lob
@Basic( fetch = FetchType.EAGER )

推荐阅读