首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将Group by添加到Hibernate条件-不带投影的查询

将Group by添加到Hibernate条件-不带投影的查询
EN

Stack Overflow用户
提问于 2010-01-10 07:20:50
回答 5查看 13.1K关注 0票数 6

我有一个Criteria- query,它连接第二个表B,从表A中选择实体。问题是,这个查询多次返回表A中的一些实体。但我需要的结果是不同的。

使用Criteria.DISTINCT_ROOT_ENTITY是没有用的,因为这会在执行SQL查询后过滤掉多次出现的情况。因此,当我将我的结果限制为20个匹配时,我最终只得到了4个,尽管有更多的条目,匹配我的查询。

在纯SQL中,我可以简单地将"GROUP BY ID“添加到查询中,一切都很好,因为表B的连接仅用于选择表A中的实体。但是使用Criteria-API我无法做到这一点。添加"GROUP BY“的唯一方法是使用投影。但是,我最终得到了标量值,而不是我的类的一个真正的实例。使用SQL限制也不起作用,因为hibernate在我的"GROUP BY"-clause后面添加了一个虚假的"1=1“。:(

有什么想法吗?

EN

回答 5

Stack Overflow用户

发布于 2011-11-30 02:07:15

你有没有试过用这样的东西?

代码语言:javascript
复制
    ICriteria criteria = dc.GetExecutableCriteria(RepositoryInstance.Session)
            .SetProjection(Projections.distinct(Projections.projectionList()
                    .add(Projections.property("Prop1"), "Prop1")
                    .add(Projections.property("Prop2"), "Prop2")
                    .add(Projections.property("Prop3"), "Prop3")
                    .add(Projections.property("Prop4"), "Prop4")));
    result = criteria.List();

您可以通过类的反射动态添加属性。

这将创建如下的SQl:select distinct prop1,prop2,prop3,prop4 from yourClass

我没有包括DetachedCriteria dc,因为它无关紧要。

票数 2
EN

Stack Overflow用户

发布于 2013-09-25 15:11:18

没有投影的bean分组:是不可能的,因为它是有意义的,在许多答案中你可能会发现,但大多数人不想使用投影,因为它要求他们投影每个属性,但要求必须投影一个。(并作为结果返回)。在下面的示例中,我尝试将所需的bean作为结果对象进行project

我用了一点小技巧也达到了同样的效果,我相信,首先我试图在没有投影的情况下应用group by,但我没有找到解决方案,所以我只能依靠投影。

以下是我想要实现的目标

代码语言:javascript
复制
select p.* FROM parent p INNER JOIN child c ON p.id_parent=c.id_father
WHERE c.child_name like '%?%' AND p.parent_name like '%?%' 
group by p.id_parent

在Java代码中,我希望p.*是一个Parent类,它是我的实体bean,并且我希望它是唯一的,一种方法是在一个集合中获取结果列表,但由于许多原因,我不喜欢这种方式:)

因此,我从Child.class而不是Parent.class创建了一个条件,这个技巧对我很有效。

代码语言:javascript
复制
Criteria c = session.createCriteria(Child.class,"c");// starting from Child
    c.add(Restrictions.like("childName",   "abc", MatchMode.ANYWHERE));
    c.createAlias("parent", "p"); //remember parent is an attribute in Child.class
    c.add(Restrictions.like("p.parentName",   "xyz", MatchMode.ANYWHERE));
    c.setProjection( Projections.projectionList().add(Projections.groupProperty("parent"))); //projecting parent which is an attribute of Child.class

    List<Parent> result = c.list(); //get the result
    for (Parent p: result) {
        System.out.println(p);
    }

如果您还不明白,这里是我的映射实体Bean类。

代码语言:javascript
复制
package com.mazhar.beans;

import static javax.persistence.GenerationType.IDENTITY;

import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name = "parent")
public class Parent {
    private Integer idParent;
    private String parentName;
    private List<Child> childs;

    @Id
    @GeneratedValue(strategy = IDENTITY)
    @Column(name = "id_parent")
    public Integer getIdParent() {
        return idParent;
    }
    public void setIdParent(Integer idParent) {
        this.idParent = idParent;
    }

    @Column(name = "parent_name")
    public String getParentName() {
        return parentName;
    }
    public void setParentName(String parentName) {
        this.parentName = parentName;
    }

    @OneToMany(fetch=FetchType.LAZY, mappedBy="parent", cascade=CascadeType.ALL)
    public List<Child> getChilds() {
        return childs;
    }
    public void setChilds(List<Child> childs) {
        this.childs = childs;
    }

}

我的孩子班级

代码语言:javascript
复制
package com.mazhar.beans;

import static javax.persistence.GenerationType.IDENTITY;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name = "child")
public class Child {
    private Integer idChild;
    private String childName;
    private Parent parent; //this actually we projected in criteria query.

    @Id
    @GeneratedValue(strategy = IDENTITY)
    @Column(name = "id_city", unique = true, nullable = false)
    public Integer getIdChild() {
        return idChild;
    }

    public void setIdChild(Integer idChild) {
        this.idChild = idChild;
    }

    @Column(name = "city_name", nullable = false)
    public String getChildName() {
        return childName;
    }

    public void setChildName(String cName) {
        this.childName = cName;
    }

    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "id_father")
    public Parent getParent() {
        return parent;
    }

    public void setParent(Parent parent) {
        this.parent = parent;
    }
}
票数 1
EN

Stack Overflow用户

发布于 2010-01-11 19:18:28

可以编写Hibernate可以用来返回实体的实际SQL查询。所以如果你真的需要的话,你可以绕过HQL,在GROUP BY中精确地编写你想要的查询。

详情请参见here

例如,您可以在hbm.xml文件中定义如下查询:

代码语言:javascript
复制
<sql-query name="exampleQuery">
<query-param name="param" type="int"/>
<return alias="x" class="foo.bar.X"/>
<return alias="y" class="foo.bar.Y"/>
    <![CDATA[
        select {x.*}, {y.*}
        from XEntity x
        inner join YEntity y on y.xId = x.id
        where y.value = :param
    ]]>
</sql-query>

请注意用于选择实体X和实体Y的所有属性的{x.}和{y.}速记语法

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2035359

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档