惰性加载在使用hibernate的JPA中不起作用

惰性加载在使用hibernate的JPA中不起作用,hibernate,jpa,spring-data-jpa,lazy-loading,mapstruct,Hibernate,Jpa,Spring Data Jpa,Lazy Loading,Mapstruct,我在spring boot应用程序中使用JPA和hibernate。每当我尝试使用jpa方法获取enities时,它都会返回实体以及其中存在的所有关联。我希望按需获取相关实体(延迟加载),因此我在域类中提供了fetch=FetchType.lazy。但它仍然返回所有条目 代码如下: Case.java @Entity @Table(name="smss_case") public class Case implements Serializable { /**

我在spring boot应用程序中使用JPA和hibernate。每当我尝试使用jpa方法获取enities时,它都会返回实体以及其中存在的所有关联。我希望按需获取相关实体(延迟加载),因此我在域类中提供了fetch=FetchType.lazy。但它仍然返回所有条目

代码如下: Case.java

    @Entity
    @Table(name="smss_case")
    public class Case implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = -2608745044895898119L;

    @Id
    @Column(name = "case_id", nullable = false)
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer caseId;

    @Column( name="case_title" )
    private String caseTitle;

    @JsonManagedReference
    @OneToMany(mappedBy="smmsCase", cascade = CascadeType.ALL, fetch=FetchType.LAZY)
    private Set<Task> tasks;

    }

}
@Entity
@Table(name="task_prop")
public class Task implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = -483515808714392369L;

    @Id
    @Column(name = "task_id", nullable = false)
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer taskId;

    @Column(name="task_title")
    private String taskTitle;

    @JsonBackReference
    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn( name="case_id", nullable=false)
    private Case smmsCase;
// getters and setters
}
public Case getCases(Integer id) {
        return dao.findById(1).get();
}
public interface ServiceDao extends JpaRepository<Case, Integer>{

}
Service.java

    @Entity
    @Table(name="smss_case")
    public class Case implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = -2608745044895898119L;

    @Id
    @Column(name = "case_id", nullable = false)
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer caseId;

    @Column( name="case_title" )
    private String caseTitle;

    @JsonManagedReference
    @OneToMany(mappedBy="smmsCase", cascade = CascadeType.ALL, fetch=FetchType.LAZY)
    private Set<Task> tasks;

    }

}
@Entity
@Table(name="task_prop")
public class Task implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = -483515808714392369L;

    @Id
    @Column(name = "task_id", nullable = false)
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer taskId;

    @Column(name="task_title")
    private String taskTitle;

    @JsonBackReference
    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn( name="case_id", nullable=false)
    private Case smmsCase;
// getters and setters
}
public Case getCases(Integer id) {
        return dao.findById(1).get();
}
public interface ServiceDao extends JpaRepository<Case, Integer>{

}
Dao.java

    @Entity
    @Table(name="smss_case")
    public class Case implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = -2608745044895898119L;

    @Id
    @Column(name = "case_id", nullable = false)
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer caseId;

    @Column( name="case_title" )
    private String caseTitle;

    @JsonManagedReference
    @OneToMany(mappedBy="smmsCase", cascade = CascadeType.ALL, fetch=FetchType.LAZY)
    private Set<Task> tasks;

    }

}
@Entity
@Table(name="task_prop")
public class Task implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = -483515808714392369L;

    @Id
    @Column(name = "task_id", nullable = false)
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer taskId;

    @Column(name="task_title")
    private String taskTitle;

    @JsonBackReference
    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn( name="case_id", nullable=false)
    private Case smmsCase;
// getters and setters
}
public Case getCases(Integer id) {
        return dao.findById(1).get();
}
public interface ServiceDao extends JpaRepository<Case, Integer>{

}
公共接口服务DAO扩展了JpaRepository{
}
{
“caseId”:1, “案例名称”:“人体工程学”, “任务”:[
{
“任务ID”:1, “任务标题”:“ca” }, {
“任务ID”:2, “任务标题”:“危险” }, {
“任务ID”:3, “任务标题”:“补救措施” } ] }

任何帮助都将不胜感激


谢谢

很难调查,但我在使用时遇到了这个问题,在这个过程中,它调用了lazy-loaded属性的getter。当我在映射之前使用mapstrct
@时,问题得到了解决

@Mapper
public interface HibernateAwareMapper {
    @BeforeMapping
    default <T> Set<T> fixLazyLoadingSet(Collection<?> c, @TargetType Class<?> targetType) {
        if (!Util.wasInitialized(c)) {
            return Collections.emptySet();
        }
        return null;
    }

    @BeforeMapping
    default <T> List<T> fixLazyLoadingList(Collection<?> c, @TargetType Class<?> targetType) {
        if (!Util.wasInitialized(c)) {
            return Collections.emptyList();
        }
        return null;
    }

   class Util {
       static boolean wasInitialized(Object c) {
           if (!(c instanceof PersistentCollection)) {
               return true;
           }

           PersistentCollection pc = (PersistentCollection) c;
           return pc.wasInitialized();
       }
   }
}
@Mapper
公共接口HibernateAwareMapper{
@制图前
默认设置fixLazyLoadingSet(集合c,@TargetType类TargetType){
如果(!Util.wasInitialized(c)){
返回集合;
}
返回null;
}
@制图前
默认列表fixLazyLoadingList(集合c,@TargetType类TargetType){
如果(!Util.wasInitialized(c)){
返回集合。emptyList();
}
返回null;
}
类Util{
静态布尔值已初始化(对象c){
if(!(PersistentCollection的c实例)){
返回true;
}
PersistentCollection pc=(PersistentCollection)c;
返回pc.wasInitialized();
}
}
}

是什么让你认为延迟加载不起作用?我猜:您正在将一个案例序列化为JSON,您可以在JSON中看到它的任务。延迟加载并不意味着“不加载”。这意味着当某个东西(比如JSON序列化程序)调用任务集的一个方法(对它们进行序列化)时,JPA执行查询以加载任务。延迟加载工作正常。你只是不明白这是什么意思。顺便说一句,在OneToMany上设置fetch=LAZY是没有用的,因为这是默认值。@JB Nizet,谢谢你的回答。我仍然感到困惑。在我的服务中,我没有调用任务集的任何方法。仍然是getCases()我的服务中的方法正在加载所有相关的任务。请告诉我这里出了什么问题。谢谢!“当某些东西(如JSON序列化程序)调用任务集的方法(以序列化它们)时”“.JSON序列化不是靠魔法实现的。JSON序列化程序遍历对象的所有属性以获取它们的值并将它们转换为JSON。如果它们是一个集合(与您的任务集类似),它将使用迭代器()方法在集合中进行迭代。这会触发延迟加载。你能分享你的控制器代码吗?您是直接返回实体还是返回表示实体的dto?这可能是因为您返回了实体本身,而序列化程序在序列化时调用了相关模型。@JB Nizet,非常感谢!!你是对的。延迟加载实际上正在工作,但当我尝试从API返回对象时,它正在调用关联的实体。@Emre Savcı,谢谢你的回复,我成功了。如上所述,当控制器返回实体时,对象到json序列化将触发关联。为此,我配置了MappingJackson2HttpMessageConverter。(参考资料:)