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

Sky*_*nzz 15 java spring hibernate jpa spring-boot

我有两个类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;
    }
}
Run Code Online (Sandbox Code Playgroud)

和 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

id:123
name:"hisName"
number:"321"
details:"some details"
registeredTimeWindow:{PersistentBag@10927}Unable to evaluate the expression Method threw 'org.hibernate.LazyInitializationException' exception.
Run Code Online (Sandbox Code Playgroud)

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

FetchType.EAGER 工作正常,但我负担不起。我尝试向比我更有经验的人寻求帮助,但没有成功。应该可以在 JPA 存储库中解决这个问题,但感觉不能使用 getter 太浪费了。

小智 26

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

  • @Transactional 来自 org.springframework.transaction.annotation.Transactional; (2认同)

小智 14

我收到此错误:

方法抛出“org.hibernate.LazyInitializationException”异常。

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

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

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

或者

@事务性