延迟加载不起作用 - 我只需要父对象,而不是所有关联
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(延迟加载)子组件中不起作用