【问题标题】:Hibernate query not returning full object休眠查询不返回完整对象
【发布时间】:2011-01-10 00:07:10
【问题描述】:

我有一个物品清单。每个项目都有一组类别。我想获取特定类别的所有项目。这部分很简单。我遇到问题的部分是让我的查询返回包含所有类别的项目,而不仅仅是我过滤的那个。

session.createCriteria(Item.class) .createAlias("categories","category") .add(Restrictions.eq("category.name",categoryFilter))

上面的代码返回项目,但只返回我过滤的类别。无论如何要说在这个限制上过滤对象,但返回完整的对象而不是过滤的对象?我也试过用 HQL 写这个,结果是一样的。

【问题讨论】:

    标签: hibernate


    【解决方案1】:

    FetchMode 和 createAlias 之间似乎确实存在一些令人讨厌的交互,这对我来说似乎是一个错误。

    https://forums.hibernate.org/viewtopic.php?t=944439 对此进行了一些讨论,其中一位开发人员强调说这是正确的行为,不会被修复。

    不过,讨论中还包含潜在的解决方法。

    尝试使用嵌套条件而不是别名:

    session.createCriteria(Item.class)
       .createCriteria("categories")
           .add(Restrictions.eq("name",categoryFilter))
    

    由于集合映射为渴望,这似乎对我有用。不确定与在外部条件上使用 FetchMode 的交互。

    【讨论】:

      【解决方案2】:

      这可能与别名和限制的使用没有太大关系,而只是默认延迟获取的结果。

      在您的 Item 映射中,您可能将类别设置为延迟获取,这是默认设置,通常是个好主意。

      您可以将此映射更改为渴望,但这可能是个坏主意。

      要保留默认的 fetch 惰性但让特定条件快速检索,您可以在此处设置 fetch 模式,类似于

      session.createCriteria(Item.class)
          .setFetchMode("categories", FetchMode.EAGER)
          .createAlias("categories","category")
          .add(Restrictions.eq("category.name",categoryFilter))
      

      【讨论】:

      • 我已经仔细检查了急切的映射,并且我已经设置了 fetchmode,如您所示。两者都没有成功。
      • 我现在已经尝试过类似的情况,实际上这不起作用。我自己还没有修复所需的休眠版本,但是有一个修订版允许将 FetchType 规范作为 createAlias 的第三个参数,这可能会做到。见opensource.atlassian.com/projects/hibernate/browse/HHH-1696
      • 根据我自己的评论 - 我确实在 Criteria 中有重载,但第三个参数不是 FetchType,而是 CriteriaSpecification。我还没有看到它纠正了这个问题。引用的 jira 用于将此重载添加到 DetachedCriteria,这在此处不起作用。
      • 我尝试将第三个参数设置为 Left_Join,它具有通常的结果。我还尝试使用 Full_Join,它创建了一个损坏的 SQL 查询。
      【解决方案3】:

      如果是错误I reported a while ago:我通常的解决方法是只获取匹配项目的id,然后在后续查询中选择项目及其类别:

      List<Serializable> ids = session.createCriteria(Item.class)
          .createAlias("categories","category")
          .add(Restrictions.eq("category.name",categoryFilter))
          .setProjection(Projections.id())
          .list();
      
      List<Items> items = session.createCriteria(Item.class)
          .add(Restrictions.in("id", ids)
          .createAlias("categories","category")
          .list();
      

      【讨论】:

        【解决方案4】:

        另一个解决方案是使用 Exists 子查询,这样 FetchMode.JOIN 也可以工作。 (这里使用 DetachedCriteria 但 Criteria 应该类似)

        DetachedCriteria criteria = session.createCriteria(Item.class, "i");
        criteria.setFetchMode("categories", FetchMode.JOIN);
        
        DetachedCriteria catCriteria = DetachedCriteria.forClass(Category.class, "category");
        catCriteria.add(Restrictions.eq("name", categoryFilter));
        catCriteria.add(Restrictions.eqProperty("category.id", "i.categoryId"));
        criteria.add(Subqueries.exists(catCriteria.setProjection(Projections.property("category.id"))));
        

        希望这对其他人也有帮助,因为文档很难弄清楚。我还添加了一个 github gist 和额外的 cmets

        【讨论】:

          猜你喜欢
          • 2013-03-16
          • 1970-01-01
          • 1970-01-01
          • 2016-09-20
          • 1970-01-01
          • 1970-01-01
          • 2018-06-08
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多