【问题标题】:MultipleBagFetch when starting application启动应用程序时的 MultipleBagFetch
【发布时间】:2025-12-21 15:40:06
【问题描述】:

我的应用程序出现以下错误:

SEVERE: Exception sending context initialized event to listener instance of class com.puntobile.videre.util.VidereContextListener
javax.persistence.PersistenceException: [PersistenceUnit: Videre] Unable to build EntityManagerFactory

当我更改我的 DAO 并在使用它时关闭每个 EntityManager 会话时发生这种情况,我以前没有这样做,这是一种不好的做法。出于这个原因,我不得不将 fetch=EAGER 添加到我的收藏中。这是我的三个实体:

package com.puntobile.videre.data;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.*;

import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;

@Entity
@SequenceGenerator(name="user_seq", sequenceName="user_seq", allocationSize=1, initialValue=1)
@Table(name="users")
public class User {

    @Id
    @GeneratedValue(generator="user_seq", strategy=GenerationType.SEQUENCE)
    private Long id;
    @Column(name="userName")
    private String userName;
    @Column(name="password")
    private String password;
    @Column(name="accessLevel")
    private int accessLevel;

    @OneToMany(mappedBy="user", fetch=FetchType.EAGER)
    @LazyCollection(LazyCollectionOption.FALSE)
    private List<Sign> signs;

    public User() {}

    public User(String userName, String password, int accessLevel) {
        this.userName = userName;
        this.password = password;
        this.accessLevel = accessLevel;
        this.signs = new ArrayList<Sign>();
    }

    public Long getId() {
        return id;
    }

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

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public int getAccessLevel() {
        return accessLevel;
    }

    public void setAccessLevel(int accessLevel) {
        this.accessLevel = accessLevel;
    }

    public void setSigns(List<Sign> signs) {
        this.signs = signs;
    }

    public List<Sign> getSigns() {
        return signs;
    }   
}

另一个:

package com.puntobile.videre.data;

import java.util.List;

import javax.persistence.*;

import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
import org.hibernate.annotations.Type;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;

@Entity
@SequenceGenerator(name="sign_seq", sequenceName="sign_seq", allocationSize=1, initialValue=1)
public class Sign {
    @Id
    @GeneratedValue(generator="sign_seq", strategy=GenerationType.SEQUENCE)
    private Long id;
    @Column(name="signName")
    private String name;
    @Column(name="url")
    private String url;
    @Column(name="description")
    private String description;
    @Column(name="lastOnline", nullable=false)
    @Type(type="org.jadira.usertype.dateandtime.joda.PersistentDateTime")
    private DateTime lastOnline;

    @ManyToOne(fetch=FetchType.EAGER)
    private User user;

    @OneToMany(mappedBy="sign", fetch=FetchType.EAGER)
    @LazyCollection(LazyCollectionOption.FALSE)
    private List<DayVideo> videos;

    public Sign() {}

    public Long getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public List<DayVideo> getVideos() {
        return videos;
    }

    public void setVideos(List<DayVideo> videos) {
        this.videos = videos;
    }

    public DateTime getLastOnline() {
        return lastOnline;
    }

    public void setLastOnline(DateTime lastOnline) {
        this.lastOnline = lastOnline;
    }


}

最后一个:

package com.puntobile.videre.data;

import javax.persistence.*;

import org.hibernate.annotations.Type;
import org.joda.time.LocalDate;

@Entity
@SequenceGenerator(name="dayvideo_seq", sequenceName="dayvideo_seq", allocationSize=1, initialValue=1)
public class DayVideo { 

    @Id
    @GeneratedValue(generator="dayvideo_seq", strategy=GenerationType.SEQUENCE)
    private Long id;
    @Column(name="startDate", nullable=false)
    @Type(type="org.jadira.usertype.dateandtime.joda.PersistentLocalDate")
    LocalDate startDate;
    @Column(name="endDate", nullable=false)
    @Type(type="org.jadira.usertype.dateandtime.joda.PersistentLocalDate")
    LocalDate endDate;
    @Column(name="videoName")
    String videoName;
    @ManyToOne(fetch=FetchType.EAGER) @JoinColumn(name="sign_id")
    Sign sign;

    public DayVideo() {}

    public Long getId() {
        return id;
    }

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

    public LocalDate getStartDate() {
        return startDate;
    }

    public void setStartDate(LocalDate startDate) {
        this.startDate = startDate;
    }

    public LocalDate getEndDate() {
        return endDate;
    }

    public void setEndDate(LocalDate endDate) {
        this.endDate = endDate;
    }

    public String getVideoName() {
        return videoName;
    }

    public void setVideoName(String videoName) {
        this.videoName = videoName;
    }

    public Sign getSign() {
        return sign;
    }

    public void setSign(Sign sign) {
        this.sign = sign;
    }

}

【问题讨论】:

    标签: java hibernate jpa entity vaadin


    【解决方案1】:

    JPA annotations are parsed not to allow more than 2 eagerly loaded collection.

    Hibernate cannot simultaneously fetch multiple bags

    所以,我怀疑您不能在同一个类中使用 fetch = EAGER 有两个 @OneToMany 注释。

    【讨论】:

    • 所以我只需要在我的“签名”中删除“用户”上的提取?
    • 我相信您必须删除signs 上的FetchType.EAGERvideos 上的那个,是的。
    • 根据this answer,Hibernate 的较新(JPA 2.0 兼容)版本也可能没有此限制。
    【解决方案2】:

    private List&lt;DayVideo&gt; videos 更改为private Set&lt;DayVideo&gt; videos

    【讨论】: