Spring boot 无法评估表达式方法抛出 'org.hibernate.LazyInitializationException' 异常。使用 getter,ManyToMany 关系

Posted

技术标签:

【中文标题】Spring boot 无法评估表达式方法抛出 \'org.hibernate.LazyInitializationException\' 异常。使用 getter,ManyToMany 关系【英文标题】:Spring boot Unable to evaluate the expression Method threw 'org.hibernate.LazyInitializationException' exception. using getter, ManyToMany relationSpring boot 无法评估表达式方法抛出 'org.hibernate.LazyInitializationException' 异常。使用 getter,ManyToMany 关系 【发布时间】:2021-07-15 18:14:27 【问题描述】:

我有两个类ParticipantTimeWindow。 多个参与者可以注册多个 TimeWindow,因此是 ManyToMany 关系

@Entity
@Table
public class Participant 
    @Id
    @SequenceGenerator(
            name = "participant_sequence",
            sequenceName = "particant_sequence",
            allocationSize = 1
    )
    @GeneratedValue(
            strategy = GenerationType.SEQUENCE,
            generator = "participant_sequence"
    )
    private Long id;
    private String name;
    private String number;
    private String details;

    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name = "ParticipantCreneaux")
    private Collection<TimeWindow> registeredTimeWindow;


    public Participant() 

    
    public Participant(String nom, String num, String details) 
        this.name = nom;
        this.number = num;
        this.details = details;
        this.registeredTimeWindow = new ArrayList<>();
    
    public void addTimeWindow(TimeWindow c)
        registeredTimeWindow.add(c);
    
    public void removeTimeWindow(TimeWindow c)
        registeredTimeWindow.remove(c);
    

    public String getName() 
        return name;
    

    public void setName(String name) 
        this.name = name;
    

    public String getNumber() 
        return number;
    

    public void setNumber(String number) 
        this.number = number;
    

    public String getDetails() 
        return details;
    

    public void setDetails(String details) 
        this.details = details;
    

    public void setId(Long id) 
        this.id = id;
    

    public Long getId() 
        return id;
    

    public Collection<TimeWindow> getRegisteredTimeWindow() 
        return registeredTimeWindow;
    

还有 TimeWindow 类:

@Entity
@Table
public class TimeWindow 
    @Id
    @SequenceGenerator(
            name = "creneau_sequence",
            sequenceName = "creneau_sequence",
            allocationSize = 1
    )
    @GeneratedValue(
            strategy = GenerationType.SEQUENCE,
            generator = "creneau_sequence"
    )
    private Long id;
    private LocalTime hourStart;
    private LocalTime hourEnd;

    public Collection<Participant> getListParticipants() 
        return listParticipants;
    

    @ManyToMany(fetch = FetchType.LAZY,cascade=CascadeType.ALL,mappedBy = "registeredTimeWindow")
    private Collection<Participant> listParticipants;

    public TimeWindow(LocalTime hourStart, LocalTime hourEnd) 
        this.hourStart = hourStart;
        this.hourEnd = hourEnd;
        this.listParticipants = new ArrayList<>();
    

    public TimeWindow()  

    public LocalTime getHourEnd() 
        return hourEnd;
    

    public void setHourStart(LocalTime hourStart) 
        this.hourStart = hourStart;
    

    public void setHourEnd(LocalTime hourEnd) 
        this.hourEnd = hourEnd;
    

    public LocalTime getHourStart() 
        return hourStart;
    

    public int getNbParticipants()
        return listParticipants.size();
    
    public void addParticipant(Participant participant)
        this.listParticipants.add(participant);
    
    public void removeParticipant(Participant participant)
        this.listParticipants.remove(participant);
    

    public void setId(Long id) 
        this.id = id;
    

    public Long getId() 
        return id;
    

现在我还在学习 Spring boot,到目前为止我还没有发现任何关于它的东西或任何对我有帮助的东西。

错误是当我召唤我通过 Config 类中的数据库获得的参与者的 TimeWindow 集合时。在调试器中,我的参与者看起来像这样

id:123
name:"hisName"
number:"321"
details:"some details"
registeredTimeWindow:PersistentBag@10927Unable to evaluate the expression Method threw 'org.hibernate.LazyInitializationException' exception.

起初我认为这是正常的,因为 Lazy 选项,我不得不通过 getter 调用数组,但是这是错误的,getter 给了我完全相同的对象。

FetchType.EAGER 工作正常,但我负担不起。我试图从比我更有经验的人那里获得一些帮助,但没有成功。应该可以在 JPA 存储库中解决这个问题,但感觉不能使用 getter 是一种浪费。

【问题讨论】:

我假设您的 spring.jpa.open-in-view 配置属性设置为 false?我也想知道在响应中是否成功加载了关系,或者它是否也失败了? 这能回答你的问题吗? How to fix org.hibernate.LazyInitializationException - could not initialize proxy - no Session 【参考方案1】:

您在关闭事务后尝试使用惰性数据,是的,其中一种方法是使用 EAGER。 另一种方式 - 在使用此数据的方法上使用 @Transactional。

【讨论】:

【参考方案2】:

我收到了这个错误:

方法抛出 'org.hibernate.LazyInitializationException' 异常。

这是因为当前没有会话存在。 Hibernate 打开一个会话并关闭它,但是对于“lazy = true”或“fetch = FetchType.LAZY”,这些字段由代理填充。当您尝试查找此类字段的值时,它将尝试使用活动会话访问数据库以检索数据。如果找不到此类会话,则会出现此异常。

您可以使用“lazy=false”来修复它或检查您是否正确使用了@Transcational(尝试在您的服务层而不是数据访问层中使用它),您也可以使用

@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)

@Transactional

【讨论】:

以上是关于Spring boot 无法评估表达式方法抛出 'org.hibernate.LazyInitializationException' 异常。使用 getter,ManyToMany 关系的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Spring Boot JPA 在 Postgres 中存储几何点?

Spring Batch 使用带有 Spring Boot 的 MongoDB 抛出无法确定数据库类型的嵌入式数据库驱动程序类 NONE

Spring Boot集成测试无法在命令行未指定配置文件时获取默认配置文件并抛出错误

Spring Boot + Spring Security解决UsernameNotFoundException无法被捕获的问题

Spring Boot /h2-console 使用 Spring Security 1.5.2 抛出 403

Spring Boot2 + Gradle5 + Log4j2 启动出现 StackOverflowError 问题的解决方法