延迟加载不起作用 - 我只需要父对象,而不是所有关联

Posted

技术标签:

【中文标题】延迟加载不起作用 - 我只需要父对象,而不是所有关联【英文标题】:Lazy load doesn't work - I Only need the parent object, not all associations 【发布时间】:2017-04-24 15:36:06 【问题描述】:

如何在没有所有子关联的情况下获得我想要的对象。

我有我的班级网站:

@Entity
@Table(name = "Sites")
public class Site 

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "Id_Site", unique = true, nullable = false)
    private long Id_Site;
    private String ...;
    private boolean ...;
    private long ...; 
    private Date ...;
    private Date ...;
    private String ...;

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private Set<Sequence> sequences = new HashSet<>();

    @ManyToOne
    private ... ...;

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private Set<...> ... = new HashSet<>();

    @ManyToOne
    private ... ...;

    public constructor...

    public set..
    public get..

我只需要一个 Site 对象,没有序列关联。

在我的序列表中,我有:

@Entity
@Table(name = "Sequences")
public class Sequence 

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "Id_Sequence", unique = true, nullable = false)
    private long Id_Sequence;
    private Date ....;
    private Date ....;
    private String ....;
    private String ....;
    private String ....;
    private int ....;
    private int ....;
    private double ....;
    private double ....;
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    private Set<TraceSequence> traceSequences = new HashSet<>();
    @ManyToOne(cascade = CascadeType.ALL)
    private Site site;

    public constructor...

    public set..
    public get..

当我使用 FetchType.Lazy 并调用我的方法时:

@Override
public Site findSiteByName(String Name_Site) 
    List<Site> sites = entityManager.createQuery("SELECT s FROM Site s").getResultList();
    for (Site item : sites) 
        if (item.getNom_Site().equals(Name_Site)) 
            return item;
        
    
    return null;

我收到此错误:

无法延迟初始化角色集合:xxx.xxx.xxx.xxx.xxx.site.Site.sequences,无法初始化代理 - 无会话

当我使用FetchType.EAGER 时,我不仅得到了一个Site 对象,还得到了所有序列对象,以及其他序列关联的所有对象。 (我知道这是正常反应。)

谁能知道为什么这种延迟初始化的尝试不起作用,请告诉我如何解决这个问题。

【问题讨论】:

你误会了。延迟加载 is 工作:这就是您收到错误的原因。稍后的一些代码会尝试访问惰性关联(例如 JSON 序列化程序)并且由于没有会话而无法加载。 【参考方案1】:

这些惰性错误发生在 jpa 在会话关闭后尝试获取数据时。

但是使用 eager 会影响包含该实体的所有查询。

尝试在查询中使用 join fetch 而不是 eager。

【讨论】:

是的,我同意你的看法。但是,查询中的 join fetch 而不是 eager 影响所有查询,就像只使用 Eager 一样。【参考方案2】:

您在代码中的某处调用Site.GetSequences(),可能在视图或代码的另一部分中进行迭代。看起来您提供的这段代码没有生成异常。

如果您尝试使用未加载到您的实体的集合,代码会抛出您提到的异常。

要解决此问题,请确定您在哪里使用 sequences,并在使用前通过将 fetch 更改为 EAGER 或在查询中使用 JOIN FETCH 来加载它们.

【讨论】:

感谢您的帮助,我评论了所有可以调用它的 GetSequences。但是,我的问题是:如果我使用 Join Fetch,我将获得所有序列元素(与使用 Eager 相同),并且我不需要获得序列。我只是需要站点对象而不需要所有依赖项。【参考方案3】:

返回休眠托管实体(或休眠托管实体的集合)很可能会导致此类问题,除非您在会话可用时对返回的内容和休眠填充的内容非常谨慎。

我会说创建一个 DTO(或 DTO 的集合)并按照您喜欢的方式填充其字段。有很多Entity到DTO的转换框架;我最喜欢的是ModelMapper。

我也倾向于同意使用 FetchType 的其他建议,但由于 DTO 由我们填充,我们知道我们填充了什么,而不是由 hibernate 基于注释填充的实体关系。

如果您需要 DTO 中的某些内容,您只需询问实体,由于会话在那个时间点可用,您可以填充您认为在 UI 上需要的任何字段。

我不想将这个话题劫持到 DTO 和实体,但我会这样做。

这可能也有帮助Avoid Jackson serialization on non fetched lazy objects

【讨论】:

【参考方案4】:

错误发生是因为您尝试执行 getSequences(),但由于是惰性的,并且会话已关闭休眠引发错误。 为避免此错误,在查询方法“内部”会话中读取读取序列,如下所示:

public Site findSiteByName(String Name_Site) 
        List sites = entityManager.createQuery("SELECT s FROM Sites").getResultList();
        for (Site item : sites) 
            if (item.getNom_Site().equals(Name_Site)) 
                item.getSites();
                return item;
            
        

        return null;
    

这是一个延迟加载,你在需要的时候阅读collenction!

【讨论】:

【参考方案5】:

正如上面其他 SE 成员所说,您收到此错误是因为会话已关闭。

如果你想加载一个特定的对象,那么你可以使用Hibernate.initialize 方法。它将执行一个额外的查询来获取相关实体的数据。

因此,与Eager加载相比,它是根据需要,不会一直执行

【讨论】:

【参考方案6】:

我正在开展一个项目,该项目旨在解决使用 ModelMapper 将实体映射到 DTO 时常见的 JPA 问题。这个问题已经在项目中解决了。项目链接:JPA Model Mapper

在这种情况下,我相信我们只想为所有延迟加载实体获取 null。具体到这个问题,这可以通过使用 de JPA Model Mapper 将实体映射到 DTO 来完成。

我已经在这个问题上回答了同样的问题:How to solve the LazyInitializationException when using JPA and Hibernate

【讨论】:

你能把相关信息放在这里吗?

以上是关于延迟加载不起作用 - 我只需要父对象,而不是所有关联的主要内容,如果未能解决你的问题,请参考以下文章

在 Hibernate / JPA 2.1 中延迟加载的 @OneToOne 映射不起作用?

TailwindCSS 在 Angular(延迟加载)子组件中不起作用

路由的默认 vue-cli 延迟加载代码在定义为 lambda 时不起作用

Hibernate延迟加载机制原理

指令在子模块中不起作用

数据表延迟加载不起作用