【问题标题】:Hibernate : Do not Fetch Association in criteria APi休眠:不要在标准 APi 中获取关联
【发布时间】:2016-03-10 07:49:22
【问题描述】:

我正在尝试使用标准 API 获取实体。

这是标题实体的样子

public class Header{
    @OneToMany(mappedBy = "header", cascade = CascadeType.ALL)
    @LazyCollection(LazyCollectionOption.FALSE)
    @JsonManagedReference
    private List<Item> items;
}

我可以限制不加载项目吗?我试过这个。请帮忙

Criteria criteria = session.createCriteria(Header.class);
criteria.add(Restrictions.eq("id", id));
criteria.setFetchMode("header.items",FetchMode.LAZY);
return (Header) criteria.uniqueResult();

记录了看起来像的 mysql 查询

/* MyService Health Check */ SELECT 1
        3 Query /* criteria query */ select this_.id as id1_0_0_, this_.created_at as created_2_0_0_, this_.updated_at as updated_3_0_0_, this_.created_by as created_4_0_0_, this_.description as descript5_0_0_, this_.due_date as due_date6_0_0_, this_.party_id_from as party_id7_0_0_, this_.party_id_to as party_id8_0_0_, this_.reference_id as referenc9_0_0_, this_.sub_type as sub_typ10_0_0_, this_.total_amount_with_tax as total_a11_0_0_, this_.total_amount_without_tax as total_a12_0_0_, this_.type as type13_0_0_ from headers this_ where this_.id=1
        3 Query SHOW WARNINGS
        3 Query select items0_.header_id as header_i7_0_0_, items0_.id as id1_2_0_, items0_.id as id1_2_1_, items0_.created_at as created_2_2_1_, items0_.updated_at as updated_3_2_1_, items0_.amount as amount4_2_1_, items0_.header_id as header_i7_2_1_, items0_.ignore_reco as ignore_r5_2_1_, items0_.type as type6_2_1_ from items items0_ where items0_.header_id=1

【问题讨论】:

  • 如何知道项目已加载?查询日志中是否有某些内容,或者您​​以后可以访问它们的问题?还是你想序列化它而不应该在这种情况下添加它?
  • 我在最后一行 return (Header) criteria.uniqueResult(); 放置了一个调试器。返回的响应中有项目。
  • 在这种情况下,项目列表是一个代理,将在访问时加载。因此,如果您使用调试器访问它,则应加载数据。如果查询日志会使用 uniqueResult 请求加载数据,那只会是错误的。
  • 所以你的意思是说..因为我可能正在序列化 Header 到 Response 中的 subItems。它会触发查询。?
  • 序列化将访问将触发数据“延迟”获取的项目列表,并且数据将从数据库中加载。如果您不想要这种行为,则需要在序列化发生之前将实体从持久化上下文中分离出来。

标签: java hibernate associations lazy-loading hibernate-criteria


【解决方案1】:

您可以在声明与实体的关系时定义初始化。你的代码看起来像

public class Header{
    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name="items")
    private List<Item> items;
}

你的获取代码看起来像

Criteria criteria = session.createCriteria(Header.class);
criteria.add(Restrictions.eq("id", id));
return (Header) criteria.uniqueResult();

Fetch 类型延迟初始化一个代理,以便在请求实体时立即加载它们。因此,当您尝试在会话生命周期内访问项目时,您将能够获取这些项目。

但是如果你尝试在会话生命周期之外访问,你会得到 LazyInitializationException。

【讨论】:

  • 如果我想加载项目怎么办?标准的限制应该是什么?
  • 如果你想加载所有项目,你必须确保你在活动会话中这样做。此链接stackoverflow.com/a/2192256/873976 可以提供帮助。
猜你喜欢
  • 1970-01-01
  • 2018-01-01
  • 2011-10-09
  • 1970-01-01
  • 1970-01-01
  • 2014-06-16
  • 1970-01-01
相关资源
最近更新 更多